]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
attempt to fix white flicker when r_water is toggled
[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_textureframe = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
73 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
74 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
96 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
102
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
111
112 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
113 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
114
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
118
119 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
125 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
126 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
127 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
128
129 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
134
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
139
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
147
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
152
153 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
154
155 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
156
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
158
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
166 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
167
168 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
169
170 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)"};
171
172 extern cvar_t v_glslgamma;
173
174 extern qboolean v_flipped_state;
175
176 static struct r_bloomstate_s
177 {
178         qboolean enabled;
179         qboolean hdr;
180
181         int bloomwidth, bloomheight;
182
183         int screentexturewidth, screentextureheight;
184         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
185
186         int bloomtexturewidth, bloomtextureheight;
187         rtexture_t *texture_bloom;
188
189         // arrays for rendering the screen passes
190         float screentexcoord2f[8];
191         float bloomtexcoord2f[8];
192         float offsettexcoord2f[8];
193
194         r_viewport_t viewport;
195 }
196 r_bloomstate;
197
198 r_waterstate_t r_waterstate;
199
200 /// shadow volume bsp struct with automatically growing nodes buffer
201 svbsp_t r_svbsp;
202
203 rtexture_t *r_texture_blanknormalmap;
204 rtexture_t *r_texture_white;
205 rtexture_t *r_texture_grey128;
206 rtexture_t *r_texture_black;
207 rtexture_t *r_texture_notexture;
208 rtexture_t *r_texture_whitecube;
209 rtexture_t *r_texture_normalizationcube;
210 rtexture_t *r_texture_fogattenuation;
211 rtexture_t *r_texture_gammaramps;
212 unsigned int r_texture_gammaramps_serial;
213 //rtexture_t *r_texture_fogintensity;
214
215 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
216 unsigned int r_numqueries;
217 unsigned int r_maxqueries;
218
219 typedef struct r_qwskincache_s
220 {
221         char name[MAX_QPATH];
222         skinframe_t *skinframe;
223 }
224 r_qwskincache_t;
225
226 static r_qwskincache_t *r_qwskincache;
227 static int r_qwskincache_size;
228
229 /// vertex coordinates for a quad that covers the screen exactly
230 const float r_screenvertex3f[12] =
231 {
232         0, 0, 0,
233         1, 0, 0,
234         1, 1, 0,
235         0, 1, 0
236 };
237
238 extern void R_DrawModelShadows(void);
239
240 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
241 {
242         int i;
243         for (i = 0;i < verts;i++)
244         {
245                 out[0] = in[0] * r;
246                 out[1] = in[1] * g;
247                 out[2] = in[2] * b;
248                 out[3] = in[3];
249                 in += 4;
250                 out += 4;
251         }
252 }
253
254 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
255 {
256         int i;
257         for (i = 0;i < verts;i++)
258         {
259                 out[0] = r;
260                 out[1] = g;
261                 out[2] = b;
262                 out[3] = a;
263                 out += 4;
264         }
265 }
266
267 // FIXME: move this to client?
268 void FOG_clear(void)
269 {
270         if (gamemode == GAME_NEHAHRA)
271         {
272                 Cvar_Set("gl_fogenable", "0");
273                 Cvar_Set("gl_fogdensity", "0.2");
274                 Cvar_Set("gl_fogred", "0.3");
275                 Cvar_Set("gl_foggreen", "0.3");
276                 Cvar_Set("gl_fogblue", "0.3");
277         }
278         r_refdef.fog_density = 0;
279         r_refdef.fog_red = 0;
280         r_refdef.fog_green = 0;
281         r_refdef.fog_blue = 0;
282         r_refdef.fog_alpha = 1;
283         r_refdef.fog_start = 0;
284         r_refdef.fog_end = 16384;
285         r_refdef.fog_height = 1<<30;
286         r_refdef.fog_fadedepth = 128;
287 }
288
289 static void R_BuildBlankTextures(void)
290 {
291         unsigned char data[4];
292         data[2] = 128; // normal X
293         data[1] = 128; // normal Y
294         data[0] = 255; // normal Z
295         data[3] = 128; // height
296         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
297         data[0] = 255;
298         data[1] = 255;
299         data[2] = 255;
300         data[3] = 255;
301         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
302         data[0] = 128;
303         data[1] = 128;
304         data[2] = 128;
305         data[3] = 255;
306         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
307         data[0] = 0;
308         data[1] = 0;
309         data[2] = 0;
310         data[3] = 255;
311         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
312 }
313
314 static void R_BuildNoTexture(void)
315 {
316         int x, y;
317         unsigned char pix[16][16][4];
318         // this makes a light grey/dark grey checkerboard texture
319         for (y = 0;y < 16;y++)
320         {
321                 for (x = 0;x < 16;x++)
322                 {
323                         if ((y < 8) ^ (x < 8))
324                         {
325                                 pix[y][x][0] = 128;
326                                 pix[y][x][1] = 128;
327                                 pix[y][x][2] = 128;
328                                 pix[y][x][3] = 255;
329                         }
330                         else
331                         {
332                                 pix[y][x][0] = 64;
333                                 pix[y][x][1] = 64;
334                                 pix[y][x][2] = 64;
335                                 pix[y][x][3] = 255;
336                         }
337                 }
338         }
339         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
340 }
341
342 static void R_BuildWhiteCube(void)
343 {
344         unsigned char data[6*1*1*4];
345         memset(data, 255, sizeof(data));
346         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
347 }
348
349 static void R_BuildNormalizationCube(void)
350 {
351         int x, y, side;
352         vec3_t v;
353         vec_t s, t, intensity;
354 #define NORMSIZE 64
355         unsigned char *data;
356         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
357         for (side = 0;side < 6;side++)
358         {
359                 for (y = 0;y < NORMSIZE;y++)
360                 {
361                         for (x = 0;x < NORMSIZE;x++)
362                         {
363                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
364                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
365                                 switch(side)
366                                 {
367                                 default:
368                                 case 0:
369                                         v[0] = 1;
370                                         v[1] = -t;
371                                         v[2] = -s;
372                                         break;
373                                 case 1:
374                                         v[0] = -1;
375                                         v[1] = -t;
376                                         v[2] = s;
377                                         break;
378                                 case 2:
379                                         v[0] = s;
380                                         v[1] = 1;
381                                         v[2] = t;
382                                         break;
383                                 case 3:
384                                         v[0] = s;
385                                         v[1] = -1;
386                                         v[2] = -t;
387                                         break;
388                                 case 4:
389                                         v[0] = s;
390                                         v[1] = -t;
391                                         v[2] = 1;
392                                         break;
393                                 case 5:
394                                         v[0] = -s;
395                                         v[1] = -t;
396                                         v[2] = -1;
397                                         break;
398                                 }
399                                 intensity = 127.0f / sqrt(DotProduct(v, v));
400                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
401                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
402                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
403                                 data[((side*64+y)*64+x)*4+3] = 255;
404                         }
405                 }
406         }
407         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
408         Mem_Free(data);
409 }
410
411 static void R_BuildFogTexture(void)
412 {
413         int x, b;
414 #define FOGWIDTH 256
415         unsigned char data1[FOGWIDTH][4];
416         //unsigned char data2[FOGWIDTH][4];
417         double d, r, alpha;
418
419         r_refdef.fogmasktable_start = r_refdef.fog_start;
420         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
421         r_refdef.fogmasktable_range = r_refdef.fogrange;
422         r_refdef.fogmasktable_density = r_refdef.fog_density;
423
424         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
425         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
426         {
427                 d = (x * r - r_refdef.fogmasktable_start);
428                 if(developer_extra.integer)
429                         Con_DPrintf("%f ", d);
430                 d = max(0, d);
431                 if (r_fog_exp2.integer)
432                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
433                 else
434                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
435                 if(developer_extra.integer)
436                         Con_DPrintf(" : %f ", alpha);
437                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
438                 if(developer_extra.integer)
439                         Con_DPrintf(" = %f\n", alpha);
440                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
441         }
442
443         for (x = 0;x < FOGWIDTH;x++)
444         {
445                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
446                 data1[x][0] = b;
447                 data1[x][1] = b;
448                 data1[x][2] = b;
449                 data1[x][3] = 255;
450                 //data2[x][0] = 255 - b;
451                 //data2[x][1] = 255 - b;
452                 //data2[x][2] = 255 - b;
453                 //data2[x][3] = 255;
454         }
455         if (r_texture_fogattenuation)
456         {
457                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
458                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
459         }
460         else
461         {
462                 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);
463                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
464         }
465 }
466
467 //=======================================================================================================================================================
468
469 static const char *builtinshaderstring =
470 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
471 "// written by Forest 'LordHavoc' Hale\n"
472 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
473 "\n"
474 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
475 "# define USEFOG\n"
476 "#endif\n"
477 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
478 "#define USELIGHTMAP\n"
479 "#endif\n"
480 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
481 "#define USEEYEVECTOR\n"
482 "#endif\n"
483 "\n"
484 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
485 "# extension GL_ARB_texture_rectangle : enable\n"
486 "#endif\n"
487 "\n"
488 "#ifdef USESHADOWMAP2D\n"
489 "# ifdef GL_EXT_gpu_shader4\n"
490 "#   extension GL_EXT_gpu_shader4 : enable\n"
491 "# endif\n"
492 "# ifdef GL_ARB_texture_gather\n"
493 "#   extension GL_ARB_texture_gather : enable\n"
494 "# else\n"
495 "#   ifdef GL_AMD_texture_texture4\n"
496 "#     extension GL_AMD_texture_texture4 : enable\n"
497 "#   endif\n"
498 "# endif\n"
499 "#endif\n"
500 "\n"
501 "#ifdef USESHADOWMAPCUBE\n"
502 "# extension GL_EXT_gpu_shader4 : enable\n"
503 "#endif\n"
504 "\n"
505 "//#ifdef USESHADOWSAMPLER\n"
506 "//# extension GL_ARB_shadow : enable\n"
507 "//#endif\n"
508 "\n"
509 "//#ifdef __GLSL_CG_DATA_TYPES\n"
510 "//# define myhalf half\n"
511 "//# define myhalf2 half2\n"
512 "//# define myhalf3 half3\n"
513 "//# define myhalf4 half4\n"
514 "//#else\n"
515 "# define myhalf float\n"
516 "# define myhalf2 vec2\n"
517 "# define myhalf3 vec3\n"
518 "# define myhalf4 vec4\n"
519 "//#endif\n"
520 "\n"
521 "#ifdef VERTEX_SHADER\n"
522 "uniform mat4 ModelViewProjectionMatrix;\n"
523 "#endif\n"
524 "\n"
525 "#ifdef MODE_DEPTH_OR_SHADOW\n"
526 "#ifdef VERTEX_SHADER\n"
527 "void main(void)\n"
528 "{\n"
529 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
530 "}\n"
531 "#endif\n"
532 "#else // !MODE_DEPTH_ORSHADOW\n"
533 "\n"
534 "\n"
535 "\n"
536 "\n"
537 "#ifdef MODE_SHOWDEPTH\n"
538 "#ifdef VERTEX_SHADER\n"
539 "void main(void)\n"
540 "{\n"
541 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
542 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
543 "}\n"
544 "#endif\n"
545 "\n"
546 "#ifdef FRAGMENT_SHADER\n"
547 "void main(void)\n"
548 "{\n"
549 "       gl_FragColor = gl_Color;\n"
550 "}\n"
551 "#endif\n"
552 "#else // !MODE_SHOWDEPTH\n"
553 "\n"
554 "\n"
555 "\n"
556 "\n"
557 "#ifdef MODE_POSTPROCESS\n"
558 "varying vec2 TexCoord1;\n"
559 "varying vec2 TexCoord2;\n"
560 "\n"
561 "#ifdef VERTEX_SHADER\n"
562 "void main(void)\n"
563 "{\n"
564 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
565 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
566 "#ifdef USEBLOOM\n"
567 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
568 "#endif\n"
569 "}\n"
570 "#endif\n"
571 "\n"
572 "#ifdef FRAGMENT_SHADER\n"
573 "uniform sampler2D Texture_First;\n"
574 "#ifdef USEBLOOM\n"
575 "uniform sampler2D Texture_Second;\n"
576 "#endif\n"
577 "#ifdef USEGAMMARAMPS\n"
578 "uniform sampler2D Texture_GammaRamps;\n"
579 "#endif\n"
580 "#ifdef USESATURATION\n"
581 "uniform float Saturation;\n"
582 "#endif\n"
583 "#ifdef USEVIEWTINT\n"
584 "uniform vec4 ViewTintColor;\n"
585 "#endif\n"
586 "//uncomment these if you want to use them:\n"
587 "uniform vec4 UserVec1;\n"
588 "// uniform vec4 UserVec2;\n"
589 "// uniform vec4 UserVec3;\n"
590 "// uniform vec4 UserVec4;\n"
591 "// uniform float ClientTime;\n"
592 "uniform vec2 PixelSize;\n"
593 "void main(void)\n"
594 "{\n"
595 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
596 "#ifdef USEBLOOM\n"
597 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
598 "#endif\n"
599 "#ifdef USEVIEWTINT\n"
600 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
601 "#endif\n"
602 "\n"
603 "#ifdef USEPOSTPROCESSING\n"
604 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
605 "// 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"
606 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
607 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
608 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
609 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
610 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
611 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
612 "#endif\n"
613 "\n"
614 "#ifdef USESATURATION\n"
615 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
616 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
617 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
618 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
619 "#endif\n"
620 "\n"
621 "#ifdef USEGAMMARAMPS\n"
622 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
623 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
624 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
625 "#endif\n"
626 "}\n"
627 "#endif\n"
628 "#else // !MODE_POSTPROCESS\n"
629 "\n"
630 "\n"
631 "\n"
632 "\n"
633 "#ifdef MODE_GENERIC\n"
634 "#ifdef USEDIFFUSE\n"
635 "varying vec2 TexCoord1;\n"
636 "#endif\n"
637 "#ifdef USESPECULAR\n"
638 "varying vec2 TexCoord2;\n"
639 "#endif\n"
640 "#ifdef VERTEX_SHADER\n"
641 "void main(void)\n"
642 "{\n"
643 "       gl_FrontColor = gl_Color;\n"
644 "#ifdef USEDIFFUSE\n"
645 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
646 "#endif\n"
647 "#ifdef USESPECULAR\n"
648 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
649 "#endif\n"
650 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
651 "}\n"
652 "#endif\n"
653 "\n"
654 "#ifdef FRAGMENT_SHADER\n"
655 "#ifdef USEDIFFUSE\n"
656 "uniform sampler2D Texture_First;\n"
657 "#endif\n"
658 "#ifdef USESPECULAR\n"
659 "uniform sampler2D Texture_Second;\n"
660 "#endif\n"
661 "\n"
662 "void main(void)\n"
663 "{\n"
664 "       gl_FragColor = gl_Color;\n"
665 "#ifdef USEDIFFUSE\n"
666 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
667 "#endif\n"
668 "\n"
669 "#ifdef USESPECULAR\n"
670 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
671 "# ifdef USECOLORMAPPING\n"
672 "       gl_FragColor *= tex2;\n"
673 "# endif\n"
674 "# ifdef USEGLOW\n"
675 "       gl_FragColor += tex2;\n"
676 "# endif\n"
677 "# ifdef USEVERTEXTEXTUREBLEND\n"
678 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
679 "# endif\n"
680 "#endif\n"
681 "}\n"
682 "#endif\n"
683 "#else // !MODE_GENERIC\n"
684 "\n"
685 "\n"
686 "\n"
687 "\n"
688 "#ifdef MODE_BLOOMBLUR\n"
689 "varying TexCoord;\n"
690 "#ifdef VERTEX_SHADER\n"
691 "void main(void)\n"
692 "{\n"
693 "       gl_FrontColor = gl_Color;\n"
694 "       TexCoord = gl_MultiTexCoord0.xy;\n"
695 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
696 "}\n"
697 "#endif\n"
698 "\n"
699 "#ifdef FRAGMENT_SHADER\n"
700 "uniform sampler2D Texture_First;\n"
701 "uniform vec4 BloomBlur_Parameters;\n"
702 "\n"
703 "void main(void)\n"
704 "{\n"
705 "       int i;\n"
706 "       vec2 tc = TexCoord;\n"
707 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
708 "       tc += BloomBlur_Parameters.xy;\n"
709 "       for (i = 1;i < SAMPLES;i++)\n"
710 "       {\n"
711 "               color += texture2D(Texture_First, tc).rgb;\n"
712 "               tc += BloomBlur_Parameters.xy;\n"
713 "       }\n"
714 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
715 "}\n"
716 "#endif\n"
717 "#else // !MODE_BLOOMBLUR\n"
718 "#ifdef MODE_REFRACTION\n"
719 "varying vec2 TexCoord;\n"
720 "varying vec4 ModelViewProjectionPosition;\n"
721 "uniform mat4 TexMatrix;\n"
722 "#ifdef VERTEX_SHADER\n"
723 "\n"
724 "void main(void)\n"
725 "{\n"
726 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
727 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
728 "       ModelViewProjectionPosition = gl_Position;\n"
729 "}\n"
730 "#endif\n"
731 "\n"
732 "#ifdef FRAGMENT_SHADER\n"
733 "uniform sampler2D Texture_Normal;\n"
734 "uniform sampler2D Texture_Refraction;\n"
735 "uniform sampler2D Texture_Reflection;\n"
736 "\n"
737 "uniform vec4 DistortScaleRefractReflect;\n"
738 "uniform vec4 ScreenScaleRefractReflect;\n"
739 "uniform vec4 ScreenCenterRefractReflect;\n"
740 "uniform vec4 RefractColor;\n"
741 "uniform vec4 ReflectColor;\n"
742 "uniform float ReflectFactor;\n"
743 "uniform float ReflectOffset;\n"
744 "\n"
745 "void main(void)\n"
746 "{\n"
747 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
748 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
749 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
750 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
751 "       // FIXME temporary hack to detect the case that the reflection\n"
752 "       // gets blackened at edges due to leaving the area that contains actual\n"
753 "       // content.\n"
754 "       // Remove this 'ack once we have a better way to stop this thing from\n"
755 "       // 'appening.\n"
756 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
757 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
758 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
759 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
760 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
761 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
762 "}\n"
763 "#endif\n"
764 "#else // !MODE_REFRACTION\n"
765 "\n"
766 "\n"
767 "\n"
768 "\n"
769 "#ifdef MODE_WATER\n"
770 "varying vec2 TexCoord;\n"
771 "varying vec3 EyeVector;\n"
772 "varying vec4 ModelViewProjectionPosition;\n"
773 "#ifdef VERTEX_SHADER\n"
774 "uniform vec3 EyePosition;\n"
775 "uniform mat4 TexMatrix;\n"
776 "\n"
777 "void main(void)\n"
778 "{\n"
779 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
780 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
781 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
782 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
783 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
784 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
785 "       ModelViewProjectionPosition = gl_Position;\n"
786 "}\n"
787 "#endif\n"
788 "\n"
789 "#ifdef FRAGMENT_SHADER\n"
790 "uniform sampler2D Texture_Normal;\n"
791 "uniform sampler2D Texture_Refraction;\n"
792 "uniform sampler2D Texture_Reflection;\n"
793 "\n"
794 "uniform vec4 DistortScaleRefractReflect;\n"
795 "uniform vec4 ScreenScaleRefractReflect;\n"
796 "uniform vec4 ScreenCenterRefractReflect;\n"
797 "uniform vec4 RefractColor;\n"
798 "uniform vec4 ReflectColor;\n"
799 "uniform float ReflectFactor;\n"
800 "uniform float ReflectOffset;\n"
801 "\n"
802 "void main(void)\n"
803 "{\n"
804 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
805 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
806 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
807 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
808 "       // FIXME temporary hack to detect the case that the reflection\n"
809 "       // gets blackened at edges due to leaving the area that contains actual\n"
810 "       // content.\n"
811 "       // Remove this 'ack once we have a better way to stop this thing from\n"
812 "       // 'appening.\n"
813 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
814 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
815 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
816 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
817 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
818 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
819 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
820 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
821 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
822 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
823 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
824 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
825 "}\n"
826 "#endif\n"
827 "#else // !MODE_WATER\n"
828 "\n"
829 "\n"
830 "\n"
831 "\n"
832 "// common definitions between vertex shader and fragment shader:\n"
833 "\n"
834 "varying vec2 TexCoord;\n"
835 "#ifdef USEVERTEXTEXTUREBLEND\n"
836 "varying vec2 TexCoord2;\n"
837 "#endif\n"
838 "#ifdef USELIGHTMAP\n"
839 "varying vec2 TexCoordLightmap;\n"
840 "#endif\n"
841 "\n"
842 "#ifdef MODE_LIGHTSOURCE\n"
843 "varying vec3 CubeVector;\n"
844 "#endif\n"
845 "\n"
846 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\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 sampler2D Texture_ScreenDepth;\n"
926 "uniform sampler2D Texture_ScreenNormalMap;\n"
927 "#endif\n"
928 "#ifdef USEDEFERREDLIGHTMAP\n"
929 "uniform sampler2D Texture_ScreenDiffuse;\n"
930 "uniform sampler2D 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, ivec2(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 "uniform myhalf2 PixelToScreenTexCoord;\n"
1317 "void main(void)\n"
1318 "{\n"
1319 "       // calculate viewspace pixel position\n"
1320 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1321 "       vec3 position;\n"
1322 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1323 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1324 "       // decode viewspace pixel normal\n"
1325 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1326 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1327 "       // surfacenormal = pixel normal in viewspace\n"
1328 "       // LightVector = pixel to light in viewspace\n"
1329 "       // CubeVector = position in lightspace\n"
1330 "       // eyevector = pixel to view in viewspace\n"
1331 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1332 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1333 "#ifdef USEDIFFUSE\n"
1334 "       // calculate diffuse shading\n"
1335 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1336 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1337 "#endif\n"
1338 "#ifdef USESPECULAR\n"
1339 "       // calculate directional shading\n"
1340 "       vec3 eyevector = position * -1.0;\n"
1341 "#  ifdef USEEXACTSPECULARMATH\n"
1342 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1343 "#  else\n"
1344 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1345 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1346 "#  endif\n"
1347 "#endif\n"
1348 "\n"
1349 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1350 "       fade *= ShadowMapCompare(CubeVector);\n"
1351 "#endif\n"
1352 "\n"
1353 "#ifdef USEDIFFUSE\n"
1354 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1355 "#else\n"
1356 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1357 "#endif\n"
1358 "#ifdef USESPECULAR\n"
1359 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1360 "#else\n"
1361 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1362 "#endif\n"
1363 "\n"
1364 "# ifdef USECUBEFILTER\n"
1365 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1366 "       gl_FragData[0].rgb *= cubecolor;\n"
1367 "       gl_FragData[1].rgb *= cubecolor;\n"
1368 "# endif\n"
1369 "}\n"
1370 "#endif // FRAGMENT_SHADER\n"
1371 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1372 "\n"
1373 "\n"
1374 "\n"
1375 "\n"
1376 "#ifdef VERTEX_SHADER\n"
1377 "uniform mat4 TexMatrix;\n"
1378 "#ifdef USEVERTEXTEXTUREBLEND\n"
1379 "uniform mat4 BackgroundTexMatrix;\n"
1380 "#endif\n"
1381 "#ifdef MODE_LIGHTSOURCE\n"
1382 "uniform mat4 ModelToLight;\n"
1383 "#endif\n"
1384 "void main(void)\n"
1385 "{\n"
1386 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1387 "       gl_FrontColor = gl_Color;\n"
1388 "#endif\n"
1389 "       // copy the surface texcoord\n"
1390 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1391 "#ifdef USEVERTEXTEXTUREBLEND\n"
1392 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1393 "#endif\n"
1394 "#ifdef USELIGHTMAP\n"
1395 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1396 "#endif\n"
1397 "\n"
1398 "#ifdef MODE_LIGHTSOURCE\n"
1399 "       // transform vertex position into light attenuation/cubemap space\n"
1400 "       // (-1 to +1 across the light box)\n"
1401 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1402 "\n"
1403 "# ifdef USEDIFFUSE\n"
1404 "       // transform unnormalized light direction into tangent space\n"
1405 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1406 "       //  normalize it per pixel)\n"
1407 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1408 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1409 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1410 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1411 "# endif\n"
1412 "#endif\n"
1413 "\n"
1414 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1415 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1416 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1417 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1418 "#endif\n"
1419 "\n"
1420 "       // transform unnormalized eye direction into tangent space\n"
1421 "#ifdef USEEYEVECTOR\n"
1422 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1423 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1424 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1425 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1426 "#endif\n"
1427 "\n"
1428 "#ifdef USEFOG\n"
1429 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1430 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1431 "#endif\n"
1432 "\n"
1433 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1434 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1435 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1436 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1437 "#endif\n"
1438 "\n"
1439 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1440 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1441 "\n"
1442 "#ifdef USEREFLECTION\n"
1443 "       ModelViewProjectionPosition = gl_Position;\n"
1444 "#endif\n"
1445 "}\n"
1446 "#endif // VERTEX_SHADER\n"
1447 "\n"
1448 "\n"
1449 "\n"
1450 "\n"
1451 "#ifdef FRAGMENT_SHADER\n"
1452 "#ifdef USEDEFERREDLIGHTMAP\n"
1453 "uniform myhalf2 PixelToScreenTexCoord;\n"
1454 "uniform myhalf3 DeferredMod_Diffuse;\n"
1455 "uniform myhalf3 DeferredMod_Specular;\n"
1456 "#endif\n"
1457 "uniform myhalf3 Color_Ambient;\n"
1458 "uniform myhalf3 Color_Diffuse;\n"
1459 "uniform myhalf3 Color_Specular;\n"
1460 "uniform myhalf SpecularPower;\n"
1461 "#ifdef USEGLOW\n"
1462 "uniform myhalf3 Color_Glow;\n"
1463 "#endif\n"
1464 "uniform myhalf Alpha;\n"
1465 "#ifdef USEREFLECTION\n"
1466 "uniform vec4 DistortScaleRefractReflect;\n"
1467 "uniform vec4 ScreenScaleRefractReflect;\n"
1468 "uniform vec4 ScreenCenterRefractReflect;\n"
1469 "uniform myhalf4 ReflectColor;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTDIRECTION\n"
1472 "uniform myhalf3 LightColor;\n"
1473 "#endif\n"
1474 "#ifdef MODE_LIGHTSOURCE\n"
1475 "uniform myhalf3 LightColor;\n"
1476 "#endif\n"
1477 "void main(void)\n"
1478 "{\n"
1479 "#ifdef USEOFFSETMAPPING\n"
1480 "       // apply offsetmapping\n"
1481 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1482 "#define TexCoord TexCoordOffset\n"
1483 "#endif\n"
1484 "\n"
1485 "       // combine the diffuse textures (base, pants, shirt)\n"
1486 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1487 "#ifdef USEALPHAKILL\n"
1488 "       if (color.a < 0.5)\n"
1489 "               discard;\n"
1490 "#endif\n"
1491 "       color.a *= Alpha;\n"
1492 "#ifdef USECOLORMAPPING\n"
1493 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1494 "#endif\n"
1495 "#ifdef USEVERTEXTEXTUREBLEND\n"
1496 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1497 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1498 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1499 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1500 "       color.a = 1.0;\n"
1501 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1502 "#endif\n"
1503 "\n"
1504 "       // get the surface normal\n"
1505 "#ifdef USEVERTEXTEXTUREBLEND\n"
1506 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1507 "#else\n"
1508 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1509 "#endif\n"
1510 "\n"
1511 "       // get the material colors\n"
1512 "       myhalf3 diffusetex = color.rgb;\n"
1513 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1514 "# ifdef USEVERTEXTEXTUREBLEND\n"
1515 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1516 "# else\n"
1517 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1518 "# endif\n"
1519 "#endif\n"
1520 "\n"
1521 "\n"
1522 "\n"
1523 "\n"
1524 "#ifdef MODE_LIGHTSOURCE\n"
1525 "       // light source\n"
1526 "#ifdef USEDIFFUSE\n"
1527 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1528 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1529 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1530 "#ifdef USESPECULAR\n"
1531 "#ifdef USEEXACTSPECULARMATH\n"
1532 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1533 "#else\n"
1534 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1535 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1536 "#endif\n"
1537 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1538 "#endif\n"
1539 "#else\n"
1540 "       color.rgb = diffusetex * Color_Ambient;\n"
1541 "#endif\n"
1542 "       color.rgb *= LightColor;\n"
1543 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1544 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1545 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1546 "#endif\n"
1547 "# ifdef USECUBEFILTER\n"
1548 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1549 "# endif\n"
1550 "#endif // MODE_LIGHTSOURCE\n"
1551 "\n"
1552 "\n"
1553 "\n"
1554 "\n"
1555 "#ifdef MODE_LIGHTDIRECTION\n"
1556 "#define SHADING\n"
1557 "#ifdef USEDIFFUSE\n"
1558 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1559 "#endif\n"
1560 "#define lightcolor LightColor\n"
1561 "#endif // MODE_LIGHTDIRECTION\n"
1562 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1563 "#define SHADING\n"
1564 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1565 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1566 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1567 "       // convert modelspace light vector to tangentspace\n"
1568 "       myhalf3 lightnormal;\n"
1569 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1570 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1571 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1572 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1573 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1574 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1575 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1576 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1577 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1578 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1579 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1580 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1581 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1582 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1583 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1584 "#define SHADING\n"
1585 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1586 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1587 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1588 "#endif\n"
1589 "\n"
1590 "\n"
1591 "\n"
1592 "\n"
1593 "#ifdef MODE_LIGHTMAP\n"
1594 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1595 "#endif // MODE_LIGHTMAP\n"
1596 "#ifdef MODE_VERTEXCOLOR\n"
1597 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1598 "#endif // MODE_VERTEXCOLOR\n"
1599 "#ifdef MODE_FLATCOLOR\n"
1600 "       color.rgb = diffusetex * Color_Ambient;\n"
1601 "#endif // MODE_FLATCOLOR\n"
1602 "\n"
1603 "\n"
1604 "\n"
1605 "\n"
1606 "#ifdef SHADING\n"
1607 "# ifdef USEDIFFUSE\n"
1608 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1609 "#  ifdef USESPECULAR\n"
1610 "#   ifdef USEEXACTSPECULARMATH\n"
1611 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1612 "#   else\n"
1613 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1614 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1615 "#   endif\n"
1616 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1617 "#  else\n"
1618 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1619 "#  endif\n"
1620 "# else\n"
1621 "       color.rgb = diffusetex * Color_Ambient;\n"
1622 "# endif\n"
1623 "#endif\n"
1624 "\n"
1625 "#ifdef USEDEFERREDLIGHTMAP\n"
1626 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1627 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1628 "       color.rgb += glosstex * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1629 "#endif\n"
1630 "\n"
1631 "#ifdef USEGLOW\n"
1632 "#ifdef USEVERTEXTEXTUREBLEND\n"
1633 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1634 "#else\n"
1635 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1636 "#endif\n"
1637 "#endif\n"
1638 "\n"
1639 "#ifdef USEFOG\n"
1640 "#ifdef MODE_LIGHTSOURCE\n"
1641 "       color.rgb *= myhalf(FogVertex());\n"
1642 "#else\n"
1643 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1644 "#endif\n"
1645 "#endif\n"
1646 "\n"
1647 "       // 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"
1648 "#ifdef USEREFLECTION\n"
1649 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1650 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1651 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1652 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1653 "       // FIXME temporary hack to detect the case that the reflection\n"
1654 "       // gets blackened at edges due to leaving the area that contains actual\n"
1655 "       // content.\n"
1656 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1657 "       // 'appening.\n"
1658 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1659 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1660 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1661 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1662 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1663 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1664 "#endif\n"
1665 "\n"
1666 "       gl_FragColor = vec4(color);\n"
1667 "}\n"
1668 "#endif // FRAGMENT_SHADER\n"
1669 "\n"
1670 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1671 "#endif // !MODE_DEFERREDGEOMETRY\n"
1672 "#endif // !MODE_WATER\n"
1673 "#endif // !MODE_REFRACTION\n"
1674 "#endif // !MODE_BLOOMBLUR\n"
1675 "#endif // !MODE_GENERIC\n"
1676 "#endif // !MODE_POSTPROCESS\n"
1677 "#endif // !MODE_SHOWDEPTH\n"
1678 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1679 ;
1680
1681 /*
1682 =========================================================================================================================================================
1683
1684
1685
1686 =========================================================================================================================================================
1687
1688
1689
1690 =========================================================================================================================================================
1691
1692
1693
1694 =========================================================================================================================================================
1695
1696
1697
1698 =========================================================================================================================================================
1699
1700
1701
1702 =========================================================================================================================================================
1703
1704
1705
1706 =========================================================================================================================================================
1707 */
1708
1709 const char *builtincgshaderstring =
1710 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1711 "// written by Forest 'LordHavoc' Hale\n"
1712 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1713 "\n"
1714 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1715 "# define USEFOG\n"
1716 "#endif\n"
1717 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1718 "#define USELIGHTMAP\n"
1719 "#endif\n"
1720 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1721 "#define USEEYEVECTOR\n"
1722 "#endif\n"
1723 "\n"
1724 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1725 "#ifdef VERTEX_SHADER\n"
1726 "void main\n"
1727 "(\n"
1728 "float4 gl_Vertex : POSITION,\n"
1729 "uniform float4x4 ModelViewProjectionMatrix,\n"
1730 "out float4 gl_Position : POSITION\n"
1731 ")\n"
1732 "{\n"
1733 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1734 "}\n"
1735 "#endif\n"
1736 "#else // !MODE_DEPTH_ORSHADOW\n"
1737 "\n"
1738 "\n"
1739 "\n"
1740 "\n"
1741 "#ifdef MODE_SHOWDEPTH\n"
1742 "#ifdef VERTEX_SHADER\n"
1743 "void main\n"
1744 "(\n"
1745 "float4 gl_Vertex : POSITION,\n"
1746 "uniform float4x4 ModelViewProjectionMatrix,\n"
1747 "out float4 gl_Position : POSITION,\n"
1748 "out float4 gl_FrontColor : COLOR0\n"
1749 ")\n"
1750 "{\n"
1751 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1752 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1753 "}\n"
1754 "#endif\n"
1755 "\n"
1756 "#ifdef FRAGMENT_SHADER\n"
1757 "void main\n"
1758 "(\n"
1759 "float4 gl_FrontColor : COLOR0,\n"
1760 "out float4 gl_FragColor : COLOR\n"
1761 ")\n"
1762 "{\n"
1763 "       gl_FragColor = gl_FrontColor;\n"
1764 "}\n"
1765 "#endif\n"
1766 "#else // !MODE_SHOWDEPTH\n"
1767 "\n"
1768 "\n"
1769 "\n"
1770 "\n"
1771 "#ifdef MODE_POSTPROCESS\n"
1772 "\n"
1773 "#ifdef VERTEX_SHADER\n"
1774 "void main\n"
1775 "(\n"
1776 "float4 gl_Vertex : POSITION,\n"
1777 "uniform float4x4 ModelViewProjectionMatrix,\n"
1778 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1779 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1780 "out float4 gl_Position : POSITION,\n"
1781 "out float2 TexCoord1 : TEXCOORD0,\n"
1782 "out float2 TexCoord2 : TEXCOORD1\n"
1783 ")\n"
1784 "{\n"
1785 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1786 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1787 "#ifdef USEBLOOM\n"
1788 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1789 "#endif\n"
1790 "}\n"
1791 "#endif\n"
1792 "\n"
1793 "#ifdef FRAGMENT_SHADER\n"
1794 "void main\n"
1795 "(\n"
1796 "float2 TexCoord1 : TEXCOORD0,\n"
1797 "float2 TexCoord2 : TEXCOORD1,\n"
1798 "uniform sampler2D Texture_First,\n"
1799 "#ifdef USEBLOOM\n"
1800 "uniform sampler2D Texture_Second,\n"
1801 "#endif\n"
1802 "#ifdef USEGAMMARAMPS\n"
1803 "uniform sampler2D Texture_GammaRamps,\n"
1804 "#endif\n"
1805 "#ifdef USESATURATION\n"
1806 "uniform float Saturation,\n"
1807 "#endif\n"
1808 "#ifdef USEVIEWTINT\n"
1809 "uniform float4 ViewTintColor,\n"
1810 "#endif\n"
1811 "uniform float4 UserVec1,\n"
1812 "uniform float4 UserVec2,\n"
1813 "uniform float4 UserVec3,\n"
1814 "uniform float4 UserVec4,\n"
1815 "uniform float ClientTime,\n"
1816 "uniform float2 PixelSize,\n"
1817 "out float4 gl_FragColor : COLOR\n"
1818 ")\n"
1819 "{\n"
1820 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1821 "#ifdef USEBLOOM\n"
1822 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1823 "#endif\n"
1824 "#ifdef USEVIEWTINT\n"
1825 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1826 "#endif\n"
1827 "\n"
1828 "#ifdef USEPOSTPROCESSING\n"
1829 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1830 "// 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"
1831 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1832 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1833 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1834 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1835 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1836 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1837 "#endif\n"
1838 "\n"
1839 "#ifdef USESATURATION\n"
1840 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1841 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1842 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1843 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1844 "#endif\n"
1845 "\n"
1846 "#ifdef USEGAMMARAMPS\n"
1847 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1848 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1849 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1850 "#endif\n"
1851 "}\n"
1852 "#endif\n"
1853 "#else // !MODE_POSTPROCESS\n"
1854 "\n"
1855 "\n"
1856 "\n"
1857 "\n"
1858 "#ifdef MODE_GENERIC\n"
1859 "#ifdef VERTEX_SHADER\n"
1860 "void main\n"
1861 "(\n"
1862 "float4 gl_Vertex : POSITION,\n"
1863 "uniform float4x4 ModelViewProjectionMatrix,\n"
1864 "float4 gl_Color : COLOR0,\n"
1865 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1866 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1867 "out float4 gl_Position : POSITION,\n"
1868 "out float4 gl_FrontColor : COLOR,\n"
1869 "out float2 TexCoord1 : TEXCOORD0,\n"
1870 "out float2 TexCoord2 : TEXCOORD1\n"
1871 ")\n"
1872 "{\n"
1873 "       gl_FrontColor = gl_Color;\n"
1874 "#ifdef USEDIFFUSE\n"
1875 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1876 "#endif\n"
1877 "#ifdef USESPECULAR\n"
1878 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1879 "#endif\n"
1880 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1881 "}\n"
1882 "#endif\n"
1883 "\n"
1884 "#ifdef FRAGMENT_SHADER\n"
1885 "\n"
1886 "void main\n"
1887 "(\n"
1888 "float4 gl_FrontColor : COLOR,\n"
1889 "float2 TexCoord1 : TEXCOORD0,\n"
1890 "float2 TexCoord2 : TEXCOORD1,\n"
1891 "#ifdef USEDIFFUSE\n"
1892 "uniform sampler2D Texture_First,\n"
1893 "#endif\n"
1894 "#ifdef USESPECULAR\n"
1895 "uniform sampler2D Texture_Second,\n"
1896 "#endif\n"
1897 "out float4 gl_FragColor : COLOR\n"
1898 ")\n"
1899 "{\n"
1900 "       gl_FragColor = gl_FrontColor;\n"
1901 "#ifdef USEDIFFUSE\n"
1902 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1903 "#endif\n"
1904 "\n"
1905 "#ifdef USESPECULAR\n"
1906 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1907 "# ifdef USECOLORMAPPING\n"
1908 "       gl_FragColor *= tex2;\n"
1909 "# endif\n"
1910 "# ifdef USEGLOW\n"
1911 "       gl_FragColor += tex2;\n"
1912 "# endif\n"
1913 "# ifdef USEVERTEXTEXTUREBLEND\n"
1914 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1915 "# endif\n"
1916 "#endif\n"
1917 "}\n"
1918 "#endif\n"
1919 "#else // !MODE_GENERIC\n"
1920 "\n"
1921 "\n"
1922 "\n"
1923 "\n"
1924 "#ifdef MODE_BLOOMBLUR\n"
1925 "#ifdef VERTEX_SHADER\n"
1926 "void main\n"
1927 "(\n"
1928 "float4 gl_Vertex : POSITION,\n"
1929 "uniform float4x4 ModelViewProjectionMatrix,\n"
1930 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1931 "out float4 gl_Position : POSITION,\n"
1932 "out float2 TexCoord : TEXCOORD0\n"
1933 ")\n"
1934 "{\n"
1935 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1936 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1937 "}\n"
1938 "#endif\n"
1939 "\n"
1940 "#ifdef FRAGMENT_SHADER\n"
1941 "\n"
1942 "void main\n"
1943 "(\n"
1944 "float2 TexCoord : TEXCOORD0,\n"
1945 "uniform sampler2D Texture_First,\n"
1946 "uniform float4 BloomBlur_Parameters,\n"
1947 "out float4 gl_FragColor : COLOR\n"
1948 ")\n"
1949 "{\n"
1950 "       int i;\n"
1951 "       float2 tc = TexCoord;\n"
1952 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1953 "       tc += BloomBlur_Parameters.xy;\n"
1954 "       for (i = 1;i < SAMPLES;i++)\n"
1955 "       {\n"
1956 "               color += tex2D(Texture_First, tc).rgb;\n"
1957 "               tc += BloomBlur_Parameters.xy;\n"
1958 "       }\n"
1959 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1960 "}\n"
1961 "#endif\n"
1962 "#else // !MODE_BLOOMBLUR\n"
1963 "#ifdef MODE_REFRACTION\n"
1964 "#ifdef VERTEX_SHADER\n"
1965 "void main\n"
1966 "(\n"
1967 "float4 gl_Vertex : POSITION,\n"
1968 "uniform float4x4 ModelViewProjectionMatrix,\n"
1969 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1970 "uniform float4x4 TexMatrix,\n"
1971 "uniform float3 EyePosition,\n"
1972 "out float4 gl_Position : POSITION,\n"
1973 "out float2 TexCoord : TEXCOORD0,\n"
1974 "out float3 EyeVector : TEXCOORD1,\n"
1975 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1976 ")\n"
1977 "{\n"
1978 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1979 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1980 "       ModelViewProjectionPosition = gl_Position;\n"
1981 "}\n"
1982 "#endif\n"
1983 "\n"
1984 "#ifdef FRAGMENT_SHADER\n"
1985 "void main\n"
1986 "(\n"
1987 "float2 TexCoord : TEXCOORD0,\n"
1988 "float3 EyeVector : TEXCOORD1,\n"
1989 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1990 "uniform sampler2D Texture_Normal,\n"
1991 "uniform sampler2D Texture_Refraction,\n"
1992 "uniform sampler2D Texture_Reflection,\n"
1993 "uniform float4 DistortScaleRefractReflect,\n"
1994 "uniform float4 ScreenScaleRefractReflect,\n"
1995 "uniform float4 ScreenCenterRefractReflect,\n"
1996 "uniform float4 RefractColor,\n"
1997 "out float4 gl_FragColor : COLOR\n"
1998 ")\n"
1999 "{\n"
2000 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2001 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2002 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2003 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2004 "       // FIXME temporary hack to detect the case that the reflection\n"
2005 "       // gets blackened at edges due to leaving the area that contains actual\n"
2006 "       // content.\n"
2007 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2008 "       // 'appening.\n"
2009 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2010 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2011 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2012 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2013 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2014 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2015 "}\n"
2016 "#endif\n"
2017 "#else // !MODE_REFRACTION\n"
2018 "\n"
2019 "\n"
2020 "\n"
2021 "\n"
2022 "#ifdef MODE_WATER\n"
2023 "#ifdef VERTEX_SHADER\n"
2024 "\n"
2025 "void main\n"
2026 "(\n"
2027 "float4 gl_Vertex : POSITION,\n"
2028 "uniform float4x4 ModelViewProjectionMatrix,\n"
2029 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2030 "uniform float4x4 TexMatrix,\n"
2031 "uniform float3 EyePosition,\n"
2032 "out float4 gl_Position : POSITION,\n"
2033 "out float2 TexCoord : TEXCOORD0,\n"
2034 "out float3 EyeVector : TEXCOORD1,\n"
2035 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2036 ")\n"
2037 "{\n"
2038 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2039 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2040 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2041 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2042 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2043 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2044 "       ModelViewProjectionPosition = gl_Position;\n"
2045 "}\n"
2046 "#endif\n"
2047 "\n"
2048 "#ifdef FRAGMENT_SHADER\n"
2049 "void main\n"
2050 "(\n"
2051 "float2 TexCoord : TEXCOORD0,\n"
2052 "float3 EyeVector : TEXCOORD1,\n"
2053 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2054 "uniform sampler2D Texture_Normal,\n"
2055 "uniform sampler2D Texture_Refraction,\n"
2056 "uniform sampler2D Texture_Reflection,\n"
2057 "uniform float4 DistortScaleRefractReflect,\n"
2058 "uniform float4 ScreenScaleRefractReflect,\n"
2059 "uniform float4 ScreenCenterRefractReflect,\n"
2060 "uniform float4 RefractColor,\n"
2061 "uniform float4 ReflectColor,\n"
2062 "uniform float ReflectFactor,\n"
2063 "uniform float ReflectOffset,\n"
2064 "out float4 gl_FragColor : COLOR\n"
2065 ")\n"
2066 "{\n"
2067 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2068 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2069 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2070 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2071 "       // FIXME temporary hack to detect the case that the reflection\n"
2072 "       // gets blackened at edges due to leaving the area that contains actual\n"
2073 "       // content.\n"
2074 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2075 "       // 'appening.\n"
2076 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2077 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2078 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2079 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2080 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2081 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2082 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2083 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2084 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2085 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2086 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2087 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2088 "}\n"
2089 "#endif\n"
2090 "#else // !MODE_WATER\n"
2091 "\n"
2092 "\n"
2093 "\n"
2094 "\n"
2095 "// 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"
2096 "\n"
2097 "// fragment shader specific:\n"
2098 "#ifdef FRAGMENT_SHADER\n"
2099 "\n"
2100 "#ifdef USEFOG\n"
2101 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2102 "{\n"
2103 "       float fogfrac;\n"
2104 "#ifdef USEFOGOUTSIDE\n"
2105 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2106 "#else\n"
2107 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2108 "#endif\n"
2109 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2110 "}\n"
2111 "#endif\n"
2112 "\n"
2113 "#ifdef USEOFFSETMAPPING\n"
2114 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2115 "{\n"
2116 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2117 "       // 14 sample relief mapping: linear search and then binary search\n"
2118 "       // this basically steps forward a small amount repeatedly until it finds\n"
2119 "       // itself inside solid, then jitters forward and back using decreasing\n"
2120 "       // amounts to find the impact\n"
2121 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2122 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2123 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2124 "       float3 RT = float3(TexCoord, 1);\n"
2125 "       OffsetVector *= 0.1;\n"
2126 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2127 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2128 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2129 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2130 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2131 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2132 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2133 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2134 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2135 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2136 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2137 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2138 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2139 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2140 "       return RT.xy;\n"
2141 "#else\n"
2142 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2143 "       // this basically moves forward the full distance, and then backs up based\n"
2144 "       // on height of samples\n"
2145 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2146 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2147 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2148 "       TexCoord += OffsetVector;\n"
2149 "       OffsetVector *= 0.333;\n"
2150 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2151 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2152 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2153 "       return TexCoord;\n"
2154 "#endif\n"
2155 "}\n"
2156 "#endif // USEOFFSETMAPPING\n"
2157 "\n"
2158 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2159 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2160 "# ifndef USESHADOWMAPVSDCT\n"
2161 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2162 "{\n"
2163 "       float3 adir = abs(dir);\n"
2164 "       float2 tc;\n"
2165 "       float2 offset;\n"
2166 "       float ma;\n"
2167 "       if (adir.x > adir.y)\n"
2168 "       {\n"
2169 "               if (adir.x > adir.z) // X\n"
2170 "               {\n"
2171 "                       ma = adir.x;\n"
2172 "                       tc = dir.zy;\n"
2173 "                       offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2174 "               }\n"
2175 "               else // Z\n"
2176 "               {\n"
2177 "                       ma = adir.z;\n"
2178 "                       tc = dir.xy;\n"
2179 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2180 "               }\n"
2181 "       }\n"
2182 "       else\n"
2183 "       {\n"
2184 "               if (adir.y > adir.z) // Y\n"
2185 "               {\n"
2186 "                       ma = adir.y;\n"
2187 "                       tc = dir.xz;\n"
2188 "                       offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2189 "               }\n"
2190 "               else // Z\n"
2191 "               {\n"
2192 "                       ma = adir.z;\n"
2193 "                       tc = dir.xy;\n"
2194 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2195 "               }\n"
2196 "       }\n"
2197 "\n"
2198 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2199 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2200 "       stc.z += ShadowMap_Parameters.z;\n"
2201 "       return stc;\n"
2202 "}\n"
2203 "# else\n"
2204 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2205 "{\n"
2206 "       float3 adir = abs(dir);\n"
2207 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2208 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2209 "       float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2210 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2211 "       stc.z += ShadowMap_Parameters.z;\n"
2212 "       return stc;\n"
2213 "}\n"
2214 "# endif\n"
2215 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2216 "\n"
2217 "#ifdef USESHADOWMAPCUBE\n"
2218 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2219 "{\n"
2220 "    float3 adir = abs(dir);\n"
2221 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2222 "}\n"
2223 "#endif\n"
2224 "\n"
2225 "# ifdef USESHADOWMAPRECT\n"
2226 "#ifdef USESHADOWMAPVSDCT\n"
2227 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2228 "#else\n"
2229 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2230 "#endif\n"
2231 "{\n"
2232 "#ifdef USESHADOWMAPVSDCT\n"
2233 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2234 "#else\n"
2235 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2236 "#endif\n"
2237 "       float f;\n"
2238 "#  ifdef USESHADOWSAMPLER\n"
2239 "\n"
2240 "#    ifdef USESHADOWMAPPCF\n"
2241 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2242 "    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"
2243 "#    else\n"
2244 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2245 "#    endif\n"
2246 "\n"
2247 "#  else\n"
2248 "\n"
2249 "#    ifdef USESHADOWMAPPCF\n"
2250 "#      if USESHADOWMAPPCF > 1\n"
2251 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2252 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2253 "    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"
2254 "    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"
2255 "    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"
2256 "    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"
2257 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2258 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2259 "#      else\n"
2260 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2261 "    float2 offset = frac(shadowmaptc.xy);\n"
2262 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2263 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2264 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2265 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2266 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2267 "#      endif\n"
2268 "#    else\n"
2269 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2270 "#    endif\n"
2271 "\n"
2272 "#  endif\n"
2273 "       return f;\n"
2274 "}\n"
2275 "# endif\n"
2276 "\n"
2277 "# ifdef USESHADOWMAP2D\n"
2278 "#ifdef USESHADOWMAPVSDCT\n"
2279 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2280 "#else\n"
2281 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2282 "#endif\n"
2283 "{\n"
2284 "#ifdef USESHADOWMAPVSDCT\n"
2285 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2286 "#else\n"
2287 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2288 "#endif\n"
2289 "    float f;\n"
2290 "\n"
2291 "#  ifdef USESHADOWSAMPLER\n"
2292 "#    ifdef USESHADOWMAPPCF\n"
2293 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2294 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2295 "    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"
2296 "#    else\n"
2297 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2298 "#    endif\n"
2299 "#  else\n"
2300 "#    ifdef USESHADOWMAPPCF\n"
2301 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2302 "#      ifdef GL_ARB_texture_gather\n"
2303 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2304 "#      else\n"
2305 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2306 "#      endif\n"
2307 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2308 "    center *= ShadowMap_TextureScale;\n"
2309 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2310 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2311 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2312 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2313 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2314 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2315 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2316 "#     else\n"
2317 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2318 "#      if USESHADOWMAPPCF > 1\n"
2319 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2320 "    center *= ShadowMap_TextureScale;\n"
2321 "    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"
2322 "    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"
2323 "    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"
2324 "    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"
2325 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2326 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2327 "#      else\n"
2328 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2329 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2330 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2331 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2332 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2333 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2334 "#      endif\n"
2335 "#     endif\n"
2336 "#    else\n"
2337 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2338 "#    endif\n"
2339 "#  endif\n"
2340 "    return f;\n"
2341 "}\n"
2342 "# endif\n"
2343 "\n"
2344 "# ifdef USESHADOWMAPCUBE\n"
2345 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2346 "{\n"
2347 "    // apply depth texture cubemap as light filter\n"
2348 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2349 "    float f;\n"
2350 "#  ifdef USESHADOWSAMPLER\n"
2351 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2352 "#  else\n"
2353 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2354 "#  endif\n"
2355 "    return f;\n"
2356 "}\n"
2357 "# endif\n"
2358 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2359 "#endif // FRAGMENT_SHADER\n"
2360 "\n"
2361 "\n"
2362 "\n"
2363 "\n"
2364 "#ifdef MODE_DEFERREDGEOMETRY\n"
2365 "#ifdef VERTEX_SHADER\n"
2366 "void main\n"
2367 "(\n"
2368 "float4 gl_Vertex : POSITION,\n"
2369 "uniform float4x4 ModelViewProjectionMatrix,\n"
2370 "#ifdef USEVERTEXTEXTUREBLEND\n"
2371 "float4 gl_Color : COLOR0,\n"
2372 "#endif\n"
2373 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2374 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2375 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2376 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2377 "uniform float4x4 TexMatrix,\n"
2378 "#ifdef USEVERTEXTEXTUREBLEND\n"
2379 "uniform float4x4 BackgroundTexMatrix,\n"
2380 "#endif\n"
2381 "uniform float4x4 ModelViewMatrix,\n"
2382 "#ifdef USEOFFSETMAPPING\n"
2383 "uniform float3 EyePosition,\n"
2384 "#endif\n"
2385 "out float4 gl_Position : POSITION,\n"
2386 "out float4 gl_FrontColor : COLOR,\n"
2387 "out float4 TexCoordBoth : TEXCOORD0,\n"
2388 "#ifdef USEOFFSETMAPPING\n"
2389 "out float3 EyeVector : TEXCOORD2,\n"
2390 "#endif\n"
2391 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2392 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2393 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2394 ")\n"
2395 "{\n"
2396 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2397 "#ifdef USEVERTEXTEXTUREBLEND\n"
2398 "       gl_FrontColor = gl_Color;\n"
2399 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2400 "#endif\n"
2401 "\n"
2402 "       // transform unnormalized eye direction into tangent space\n"
2403 "#ifdef USEOFFSETMAPPING\n"
2404 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2405 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2406 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2407 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2408 "#endif\n"
2409 "\n"
2410 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2411 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2412 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2413 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2414 "}\n"
2415 "#endif // VERTEX_SHADER\n"
2416 "\n"
2417 "#ifdef FRAGMENT_SHADER\n"
2418 "void main\n"
2419 "(\n"
2420 "float4 TexCoordBoth : TEXCOORD0,\n"
2421 "float3 EyeVector : TEXCOORD2,\n"
2422 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2423 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2424 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2425 "uniform sampler2D Texture_Normal,\n"
2426 "#ifdef USEALPHAKILL\n"
2427 "uniform sampler2D Texture_Color,\n"
2428 "#endif\n"
2429 "#ifdef USEVERTEXTEXTUREBLEND\n"
2430 "uniform sampler2D Texture_SecondaryNormal,\n"
2431 "#endif\n"
2432 "#ifdef USEOFFSETMAPPING\n"
2433 "uniform float OffsetMapping_Scale,\n"
2434 "#endif\n"
2435 "uniform half SpecularPower,\n"
2436 "out float4 gl_FragColor : COLOR\n"
2437 ")\n"
2438 "{\n"
2439 "       float2 TexCoord = TexCoordBoth.xy;\n"
2440 "#ifdef USEOFFSETMAPPING\n"
2441 "       // apply offsetmapping\n"
2442 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2443 "#define TexCoord TexCoordOffset\n"
2444 "#endif\n"
2445 "\n"
2446 "#ifdef USEALPHAKILL\n"
2447 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2448 "               discard;\n"
2449 "#endif\n"
2450 "\n"
2451 "#ifdef USEVERTEXTEXTUREBLEND\n"
2452 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2453 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2454 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2455 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2456 "#endif\n"
2457 "\n"
2458 "#ifdef USEVERTEXTEXTUREBLEND\n"
2459 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2460 "#else\n"
2461 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2462 "#endif\n"
2463 "\n"
2464 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2465 "}\n"
2466 "#endif // FRAGMENT_SHADER\n"
2467 "#else // !MODE_DEFERREDGEOMETRY\n"
2468 "\n"
2469 "\n"
2470 "\n"
2471 "\n"
2472 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2473 "#ifdef VERTEX_SHADER\n"
2474 "void main\n"
2475 "(\n"
2476 "float4 gl_Vertex : POSITION,\n"
2477 "uniform float4x4 ModelViewProjectionMatrix,\n"
2478 "uniform float4x4 ModelViewMatrix,\n"
2479 "out float4 gl_Position : POSITION,\n"
2480 "out float4 ModelViewPosition : TEXCOORD0\n"
2481 ")\n"
2482 "{\n"
2483 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2484 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2485 "}\n"
2486 "#endif // VERTEX_SHADER\n"
2487 "\n"
2488 "#ifdef FRAGMENT_SHADER\n"
2489 "void main\n"
2490 "(\n"
2491 "float2 Pixel : WPOS,\n"
2492 "float4 ModelViewPosition : TEXCOORD0,\n"
2493 "uniform float4x4 ViewToLight,\n"
2494 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2495 "uniform float3 LightPosition,\n"
2496 "uniform half2 PixelToScreenTexCoord,\n"
2497 "uniform half3 DeferredColor_Ambient,\n"
2498 "uniform half3 DeferredColor_Diffuse,\n"
2499 "#ifdef USESPECULAR\n"
2500 "uniform half3 DeferredColor_Specular,\n"
2501 "uniform half SpecularPower,\n"
2502 "#endif\n"
2503 "uniform sampler2D Texture_Attenuation,\n"
2504 "uniform sampler2D Texture_ScreenDepth,\n"
2505 "uniform sampler2D Texture_ScreenNormalMap,\n"
2506 "\n"
2507 "#ifdef USESHADOWMAPRECT\n"
2508 "# ifdef USESHADOWSAMPLER\n"
2509 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2510 "# else\n"
2511 "uniform samplerRECT Texture_ShadowMapRect,\n"
2512 "# endif\n"
2513 "#endif\n"
2514 "\n"
2515 "#ifdef USESHADOWMAP2D\n"
2516 "# ifdef USESHADOWSAMPLER\n"
2517 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2518 "# else\n"
2519 "uniform sampler2D Texture_ShadowMap2D,\n"
2520 "# endif\n"
2521 "#endif\n"
2522 "\n"
2523 "#ifdef USESHADOWMAPVSDCT\n"
2524 "uniform samplerCUBE Texture_CubeProjection,\n"
2525 "#endif\n"
2526 "\n"
2527 "#ifdef USESHADOWMAPCUBE\n"
2528 "# ifdef USESHADOWSAMPLER\n"
2529 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2530 "# else\n"
2531 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2532 "# endif\n"
2533 "#endif\n"
2534 "\n"
2535 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2536 "uniform float2 ShadowMap_TextureScale,\n"
2537 "uniform float4 ShadowMap_Parameters,\n"
2538 "#endif\n"
2539 "\n"
2540 "out float4 gl_FragData0 : COLOR0,\n"
2541 "out float4 gl_FragData1 : COLOR1\n"
2542 ")\n"
2543 "{\n"
2544 "       // calculate viewspace pixel position\n"
2545 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2546 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2547 "       float3 position;\n"
2548 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2549 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2550 "       // decode viewspace pixel normal\n"
2551 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2552 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2553 "       // surfacenormal = pixel normal in viewspace\n"
2554 "       // LightVector = pixel to light in viewspace\n"
2555 "       // CubeVector = position in lightspace\n"
2556 "       // eyevector = pixel to view in viewspace\n"
2557 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2558 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2559 "#ifdef USEDIFFUSE\n"
2560 "       // calculate diffuse shading\n"
2561 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2562 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2563 "#endif\n"
2564 "#ifdef USESPECULAR\n"
2565 "       // calculate directional shading\n"
2566 "       float3 eyevector = position * -1.0;\n"
2567 "#  ifdef USEEXACTSPECULARMATH\n"
2568 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2569 "#  else\n"
2570 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2571 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2572 "#  endif\n"
2573 "#endif\n"
2574 "\n"
2575 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2576 "       fade *= ShadowMapCompare(CubeVector,\n"
2577 "# if defined(USESHADOWMAP2D)\n"
2578 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2579 "# endif\n"
2580 "# if defined(USESHADOWMAPRECT)\n"
2581 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2582 "# endif\n"
2583 "# if defined(USESHADOWMAPCUBE)\n"
2584 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2585 "# endif\n"
2586 "\n"
2587 "#ifdef USESHADOWMAPVSDCT\n"
2588 ", Texture_CubeProjection\n"
2589 "#endif\n"
2590 "       );\n"
2591 "#endif\n"
2592 "\n"
2593 "#ifdef USEDIFFUSE\n"
2594 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2595 "#else\n"
2596 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2597 "#endif\n"
2598 "#ifdef USESPECULAR\n"
2599 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2600 "#else\n"
2601 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2602 "#endif\n"
2603 "\n"
2604 "# ifdef USECUBEFILTER\n"
2605 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2606 "       gl_FragData0.rgb *= cubecolor;\n"
2607 "       gl_FragData1.rgb *= cubecolor;\n"
2608 "# endif\n"
2609 "}\n"
2610 "#endif // FRAGMENT_SHADER\n"
2611 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2612 "\n"
2613 "\n"
2614 "\n"
2615 "\n"
2616 "#ifdef VERTEX_SHADER\n"
2617 "void main\n"
2618 "(\n"
2619 "float4 gl_Vertex : POSITION,\n"
2620 "uniform float4x4 ModelViewProjectionMatrix,\n"
2621 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2622 "float4 gl_Color : COLOR0,\n"
2623 "#endif\n"
2624 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2625 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2626 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2627 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2628 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2629 "\n"
2630 "uniform float3 EyePosition,\n"
2631 "uniform float4x4 TexMatrix,\n"
2632 "#ifdef USEVERTEXTEXTUREBLEND\n"
2633 "uniform float4x4 BackgroundTexMatrix,\n"
2634 "#endif\n"
2635 "#ifdef MODE_LIGHTSOURCE\n"
2636 "uniform float4x4 ModelToLight,\n"
2637 "#endif\n"
2638 "#ifdef MODE_LIGHTSOURCE\n"
2639 "uniform float3 LightPosition,\n"
2640 "#endif\n"
2641 "#ifdef MODE_LIGHTDIRECTION\n"
2642 "uniform float3 LightDir,\n"
2643 "#endif\n"
2644 "uniform float4 FogPlane,\n"
2645 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2646 "uniform float3 LightPosition,\n"
2647 "#endif\n"
2648 "\n"
2649 "out float4 gl_FrontColor : COLOR,\n"
2650 "out float4 TexCoordBoth : TEXCOORD0,\n"
2651 "#ifdef USELIGHTMAP\n"
2652 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2653 "#endif\n"
2654 "#ifdef USEEYEVECTOR\n"
2655 "out float3 EyeVector : TEXCOORD2,\n"
2656 "#endif\n"
2657 "#ifdef USEREFLECTION\n"
2658 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2659 "#endif\n"
2660 "#ifdef USEFOG\n"
2661 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2662 "#endif\n"
2663 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2664 "out float3 LightVector : TEXCOORD5,\n"
2665 "#endif\n"
2666 "#ifdef MODE_LIGHTSOURCE\n"
2667 "out float3 CubeVector : TEXCOORD3,\n"
2668 "#endif\n"
2669 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2670 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2671 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2672 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2673 "#endif\n"
2674 "out float4 gl_Position : POSITION\n"
2675 ")\n"
2676 "{\n"
2677 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2678 "       gl_FrontColor = gl_Color;\n"
2679 "#endif\n"
2680 "       // copy the surface texcoord\n"
2681 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2682 "#ifdef USEVERTEXTEXTUREBLEND\n"
2683 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2684 "#endif\n"
2685 "#ifdef USELIGHTMAP\n"
2686 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2687 "#endif\n"
2688 "\n"
2689 "#ifdef MODE_LIGHTSOURCE\n"
2690 "       // transform vertex position into light attenuation/cubemap space\n"
2691 "       // (-1 to +1 across the light box)\n"
2692 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2693 "\n"
2694 "# ifdef USEDIFFUSE\n"
2695 "       // transform unnormalized light direction into tangent space\n"
2696 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2697 "       //  normalize it per pixel)\n"
2698 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2699 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2700 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2701 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2702 "# endif\n"
2703 "#endif\n"
2704 "\n"
2705 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2706 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2707 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2708 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2709 "#endif\n"
2710 "\n"
2711 "       // transform unnormalized eye direction into tangent space\n"
2712 "#ifdef USEEYEVECTOR\n"
2713 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2714 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2715 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2716 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2717 "#endif\n"
2718 "\n"
2719 "#ifdef USEFOG\n"
2720 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2721 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2722 "#endif\n"
2723 "\n"
2724 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2725 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2726 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2727 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2728 "#endif\n"
2729 "\n"
2730 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2731 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2732 "\n"
2733 "#ifdef USEREFLECTION\n"
2734 "       ModelViewProjectionPosition = gl_Position;\n"
2735 "#endif\n"
2736 "}\n"
2737 "#endif // VERTEX_SHADER\n"
2738 "\n"
2739 "\n"
2740 "\n"
2741 "\n"
2742 "#ifdef FRAGMENT_SHADER\n"
2743 "void main\n"
2744 "(\n"
2745 "#ifdef USEDEFERREDLIGHTMAP\n"
2746 "float2 Pixel : WPOS,\n"
2747 "#endif\n"
2748 "float4 gl_FrontColor : COLOR,\n"
2749 "float4 TexCoordBoth : TEXCOORD0,\n"
2750 "#ifdef USELIGHTMAP\n"
2751 "float2 TexCoordLightmap : TEXCOORD1,\n"
2752 "#endif\n"
2753 "#ifdef USEEYEVECTOR\n"
2754 "float3 EyeVector : TEXCOORD2,\n"
2755 "#endif\n"
2756 "#ifdef USEREFLECTION\n"
2757 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2758 "#endif\n"
2759 "#ifdef USEFOG\n"
2760 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2761 "#endif\n"
2762 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2763 "float3 LightVector : TEXCOORD5,\n"
2764 "#endif\n"
2765 "#ifdef MODE_LIGHTSOURCE\n"
2766 "float3 CubeVector : TEXCOORD3,\n"
2767 "#endif\n"
2768 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2769 "float4 ModelViewPosition : TEXCOORD0,\n"
2770 "#endif\n"
2771 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2772 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2773 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2774 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2775 "#endif\n"
2776 "\n"
2777 "uniform sampler2D Texture_Normal,\n"
2778 "uniform sampler2D Texture_Color,\n"
2779 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2780 "uniform sampler2D Texture_Gloss,\n"
2781 "#endif\n"
2782 "#ifdef USEGLOW\n"
2783 "uniform sampler2D Texture_Glow,\n"
2784 "#endif\n"
2785 "#ifdef USEVERTEXTEXTUREBLEND\n"
2786 "uniform sampler2D Texture_SecondaryNormal,\n"
2787 "uniform sampler2D Texture_SecondaryColor,\n"
2788 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2789 "uniform sampler2D Texture_SecondaryGloss,\n"
2790 "#endif\n"
2791 "#ifdef USEGLOW\n"
2792 "uniform sampler2D Texture_SecondaryGlow,\n"
2793 "#endif\n"
2794 "#endif\n"
2795 "#ifdef USECOLORMAPPING\n"
2796 "uniform sampler2D Texture_Pants,\n"
2797 "uniform sampler2D Texture_Shirt,\n"
2798 "#endif\n"
2799 "#ifdef USEFOG\n"
2800 "uniform sampler2D Texture_FogMask,\n"
2801 "#endif\n"
2802 "#ifdef USELIGHTMAP\n"
2803 "uniform sampler2D Texture_Lightmap,\n"
2804 "#endif\n"
2805 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2806 "uniform sampler2D Texture_Deluxemap,\n"
2807 "#endif\n"
2808 "#ifdef USEREFLECTION\n"
2809 "uniform sampler2D Texture_Reflection,\n"
2810 "#endif\n"
2811 "\n"
2812 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2813 "uniform sampler2D Texture_ScreenDepth,\n"
2814 "uniform sampler2D Texture_ScreenNormalMap,\n"
2815 "#endif\n"
2816 "#ifdef USEDEFERREDLIGHTMAP\n"
2817 "uniform sampler2D Texture_ScreenDiffuse,\n"
2818 "uniform sampler2D Texture_ScreenSpecular,\n"
2819 "#endif\n"
2820 "\n"
2821 "#ifdef USECOLORMAPPING\n"
2822 "uniform half3 Color_Pants,\n"
2823 "uniform half3 Color_Shirt,\n"
2824 "#endif\n"
2825 "#ifdef USEFOG\n"
2826 "uniform float3 FogColor,\n"
2827 "uniform float FogRangeRecip,\n"
2828 "uniform float FogPlaneViewDist,\n"
2829 "uniform float FogHeightFade,\n"
2830 "#endif\n"
2831 "\n"
2832 "#ifdef USEOFFSETMAPPING\n"
2833 "uniform float OffsetMapping_Scale,\n"
2834 "#endif\n"
2835 "\n"
2836 "#ifdef USEDEFERREDLIGHTMAP\n"
2837 "uniform half2 PixelToScreenTexCoord,\n"
2838 "uniform half3 DeferredMod_Diffuse,\n"
2839 "uniform half3 DeferredMod_Specular,\n"
2840 "#endif\n"
2841 "uniform half3 Color_Ambient,\n"
2842 "uniform half3 Color_Diffuse,\n"
2843 "uniform half3 Color_Specular,\n"
2844 "uniform half SpecularPower,\n"
2845 "#ifdef USEGLOW\n"
2846 "uniform half3 Color_Glow,\n"
2847 "#endif\n"
2848 "uniform half Alpha,\n"
2849 "#ifdef USEREFLECTION\n"
2850 "uniform float4 DistortScaleRefractReflect,\n"
2851 "uniform float4 ScreenScaleRefractReflect,\n"
2852 "uniform float4 ScreenCenterRefractReflect,\n"
2853 "uniform half4 ReflectColor,\n"
2854 "#endif\n"
2855 "#ifdef MODE_LIGHTDIRECTION\n"
2856 "uniform half3 LightColor,\n"
2857 "#endif\n"
2858 "#ifdef MODE_LIGHTSOURCE\n"
2859 "uniform half3 LightColor,\n"
2860 "#endif\n"
2861 "\n"
2862 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2863 "uniform sampler2D Texture_Attenuation,\n"
2864 "uniform samplerCUBE Texture_Cube,\n"
2865 "\n"
2866 "#ifdef USESHADOWMAPRECT\n"
2867 "# ifdef USESHADOWSAMPLER\n"
2868 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2869 "# else\n"
2870 "uniform samplerRECT Texture_ShadowMapRect,\n"
2871 "# endif\n"
2872 "#endif\n"
2873 "\n"
2874 "#ifdef USESHADOWMAP2D\n"
2875 "# ifdef USESHADOWSAMPLER\n"
2876 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2877 "# else\n"
2878 "uniform sampler2D Texture_ShadowMap2D,\n"
2879 "# endif\n"
2880 "#endif\n"
2881 "\n"
2882 "#ifdef USESHADOWMAPVSDCT\n"
2883 "uniform samplerCUBE Texture_CubeProjection,\n"
2884 "#endif\n"
2885 "\n"
2886 "#ifdef USESHADOWMAPCUBE\n"
2887 "# ifdef USESHADOWSAMPLER\n"
2888 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2889 "# else\n"
2890 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2891 "# endif\n"
2892 "#endif\n"
2893 "\n"
2894 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2895 "uniform float2 ShadowMap_TextureScale,\n"
2896 "uniform float4 ShadowMap_Parameters,\n"
2897 "#endif\n"
2898 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2899 "\n"
2900 "out float4 gl_FragColor : COLOR\n"
2901 ")\n"
2902 "{\n"
2903 "       float2 TexCoord = TexCoordBoth.xy;\n"
2904 "#ifdef USEVERTEXTEXTUREBLEND\n"
2905 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2906 "#endif\n"
2907 "#ifdef USEOFFSETMAPPING\n"
2908 "       // apply offsetmapping\n"
2909 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2910 "#define TexCoord TexCoordOffset\n"
2911 "#endif\n"
2912 "\n"
2913 "       // combine the diffuse textures (base, pants, shirt)\n"
2914 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2915 "#ifdef USEALPHAKILL\n"
2916 "       if (color.a < 0.5)\n"
2917 "               discard;\n"
2918 "#endif\n"
2919 "       color.a *= Alpha;\n"
2920 "#ifdef USECOLORMAPPING\n"
2921 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2922 "#endif\n"
2923 "#ifdef USEVERTEXTEXTUREBLEND\n"
2924 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2925 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2926 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2927 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2928 "       color.a = 1.0;\n"
2929 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2930 "#endif\n"
2931 "\n"
2932 "       // get the surface normal\n"
2933 "#ifdef USEVERTEXTEXTUREBLEND\n"
2934 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2935 "#else\n"
2936 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2937 "#endif\n"
2938 "\n"
2939 "       // get the material colors\n"
2940 "       half3 diffusetex = color.rgb;\n"
2941 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2942 "# ifdef USEVERTEXTEXTUREBLEND\n"
2943 "       half3 glosstex = half3(lerp(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2944 "# else\n"
2945 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2946 "# endif\n"
2947 "#endif\n"
2948 "\n"
2949 "\n"
2950 "\n"
2951 "\n"
2952 "#ifdef MODE_LIGHTSOURCE\n"
2953 "       // light source\n"
2954 "#ifdef USEDIFFUSE\n"
2955 "       half3 lightnormal = half3(normalize(LightVector));\n"
2956 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2957 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2958 "#ifdef USESPECULAR\n"
2959 "#ifdef USEEXACTSPECULARMATH\n"
2960 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2961 "#else\n"
2962 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2963 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2964 "#endif\n"
2965 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2966 "#endif\n"
2967 "#else\n"
2968 "       color.rgb = diffusetex * Color_Ambient;\n"
2969 "#endif\n"
2970 "       color.rgb *= LightColor;\n"
2971 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2972 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2973 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2974 "# if defined(USESHADOWMAP2D)\n"
2975 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2976 "# endif\n"
2977 "# if defined(USESHADOWMAPRECT)\n"
2978 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2979 "# endif\n"
2980 "# if defined(USESHADOWMAPCUBE)\n"
2981 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2982 "# endif\n"
2983 "\n"
2984 "#ifdef USESHADOWMAPVSDCT\n"
2985 ", Texture_CubeProjection\n"
2986 "#endif\n"
2987 "       );\n"
2988 "\n"
2989 "#endif\n"
2990 "# ifdef USECUBEFILTER\n"
2991 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2992 "# endif\n"
2993 "#endif // MODE_LIGHTSOURCE\n"
2994 "\n"
2995 "\n"
2996 "\n"
2997 "\n"
2998 "#ifdef MODE_LIGHTDIRECTION\n"
2999 "#define SHADING\n"
3000 "#ifdef USEDIFFUSE\n"
3001 "       half3 lightnormal = half3(normalize(LightVector));\n"
3002 "#endif\n"
3003 "#define lightcolor LightColor\n"
3004 "#endif // MODE_LIGHTDIRECTION\n"
3005 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3006 "#define SHADING\n"
3007 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3008 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3009 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3010 "       // convert modelspace light vector to tangentspace\n"
3011 "       half3 lightnormal;\n"
3012 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3013 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3014 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3015 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3016 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3017 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3018 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3019 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3020 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3021 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3022 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3023 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3024 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3025 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3026 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3027 "#define SHADING\n"
3028 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3029 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3030 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3031 "#endif\n"
3032 "\n"
3033 "\n"
3034 "\n"
3035 "\n"
3036 "#ifdef MODE_LIGHTMAP\n"
3037 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3038 "#endif // MODE_LIGHTMAP\n"
3039 "#ifdef MODE_VERTEXCOLOR\n"
3040 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3041 "#endif // MODE_VERTEXCOLOR\n"
3042 "#ifdef MODE_FLATCOLOR\n"
3043 "       color.rgb = diffusetex * Color_Ambient;\n"
3044 "#endif // MODE_FLATCOLOR\n"
3045 "\n"
3046 "\n"
3047 "\n"
3048 "\n"
3049 "#ifdef SHADING\n"
3050 "# ifdef USEDIFFUSE\n"
3051 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3052 "#  ifdef USESPECULAR\n"
3053 "#   ifdef USEEXACTSPECULARMATH\n"
3054 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3055 "#   else\n"
3056 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3057 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3058 "#   endif\n"
3059 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3060 "#  else\n"
3061 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3062 "#  endif\n"
3063 "# else\n"
3064 "       color.rgb = diffusetex * Color_Ambient;\n"
3065 "# endif\n"
3066 "#endif\n"
3067 "\n"
3068 "#ifdef USEDEFERREDLIGHTMAP\n"
3069 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3070 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3071 "       color.rgb += glosstex * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3072 "#endif\n"
3073 "\n"
3074 "#ifdef USEGLOW\n"
3075 "#ifdef USEVERTEXTEXTUREBLEND\n"
3076 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3077 "#else\n"
3078 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3079 "#endif\n"
3080 "#endif\n"
3081 "\n"
3082 "#ifdef USEFOG\n"
3083 "#ifdef MODE_LIGHTSOURCE\n"
3084 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3085 "#else\n"
3086 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3087 "#endif\n"
3088 "#endif\n"
3089 "\n"
3090 "       // 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"
3091 "#ifdef USEREFLECTION\n"
3092 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3093 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3094 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3095 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3096 "       // FIXME temporary hack to detect the case that the reflection\n"
3097 "       // gets blackened at edges due to leaving the area that contains actual\n"
3098 "       // content.\n"
3099 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3100 "       // 'appening.\n"
3101 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3102 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3103 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3104 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3105 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3106 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3107 "#endif\n"
3108 "\n"
3109 "       gl_FragColor = float4(color);\n"
3110 "}\n"
3111 "#endif // FRAGMENT_SHADER\n"
3112 "\n"
3113 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3114 "#endif // !MODE_DEFERREDGEOMETRY\n"
3115 "#endif // !MODE_WATER\n"
3116 "#endif // !MODE_REFRACTION\n"
3117 "#endif // !MODE_BLOOMBLUR\n"
3118 "#endif // !MODE_GENERIC\n"
3119 "#endif // !MODE_POSTPROCESS\n"
3120 "#endif // !MODE_SHOWDEPTH\n"
3121 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3122 ;
3123
3124 //=======================================================================================================================================================
3125
3126 typedef struct shaderpermutationinfo_s
3127 {
3128         const char *pretext;
3129         const char *name;
3130 }
3131 shaderpermutationinfo_t;
3132
3133 typedef struct shadermodeinfo_s
3134 {
3135         const char *vertexfilename;
3136         const char *geometryfilename;
3137         const char *fragmentfilename;
3138         const char *pretext;
3139         const char *name;
3140 }
3141 shadermodeinfo_t;
3142
3143 typedef enum shaderpermutation_e
3144 {
3145         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3146         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3147         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3148         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3149         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3150         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3151         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3152         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3153         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3154         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3155         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3156         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3157         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3158         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3159         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3160         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3161         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3162         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3163         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3164         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3165         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3166         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3167         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3168         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3169         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3170         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3171         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3172         SHADERPERMUTATION_COUNT = 26 ///< size of shaderpermutationinfo array
3173 }
3174 shaderpermutation_t;
3175
3176 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3177 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3178 {
3179         {"#define USEDIFFUSE\n", " diffuse"},
3180         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3181         {"#define USEVIEWTINT\n", " viewtint"},
3182         {"#define USECOLORMAPPING\n", " colormapping"},
3183         {"#define USESATURATION\n", " saturation"},
3184         {"#define USEFOGINSIDE\n", " foginside"},
3185         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3186         {"#define USEGAMMARAMPS\n", " gammaramps"},
3187         {"#define USECUBEFILTER\n", " cubefilter"},
3188         {"#define USEGLOW\n", " glow"},
3189         {"#define USEBLOOM\n", " bloom"},
3190         {"#define USESPECULAR\n", " specular"},
3191         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3192         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3193         {"#define USEREFLECTION\n", " reflection"},
3194         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3195         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3196         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3197         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3198         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3199         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3200         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3201         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3202         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3203         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3204         {"#define USEALPHAKILL\n", " alphakill"},
3205 };
3206
3207 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3208 typedef enum shadermode_e
3209 {
3210         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3211         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3212         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3213         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3214         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3215         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3216         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3217         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3218         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3219         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3220         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3221         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3222         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3223         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3224         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3225         SHADERMODE_COUNT
3226 }
3227 shadermode_t;
3228
3229 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3230 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3231 {
3232         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3233         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3234         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3235         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3236         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3237         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3238         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3239         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3240         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3241         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3242         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3243         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3244         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3245         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3246         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3247 };
3248
3249 #ifdef SUPPORTCG
3250 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3251 {
3252         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3253         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3254         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3255         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3256         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3257         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3258         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3259         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3260         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3261         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3262         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3263         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3264         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3265         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3266         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3267 };
3268 #endif
3269
3270 struct r_glsl_permutation_s;
3271 typedef struct r_glsl_permutation_s
3272 {
3273         /// hash lookup data
3274         struct r_glsl_permutation_s *hashnext;
3275         unsigned int mode;
3276         unsigned int permutation;
3277
3278         /// indicates if we have tried compiling this permutation already
3279         qboolean compiled;
3280         /// 0 if compilation failed
3281         int program;
3282         /// locations of detected uniforms in program object, or -1 if not found
3283         int loc_Texture_First;
3284         int loc_Texture_Second;
3285         int loc_Texture_GammaRamps;
3286         int loc_Texture_Normal;
3287         int loc_Texture_Color;
3288         int loc_Texture_Gloss;
3289         int loc_Texture_Glow;
3290         int loc_Texture_SecondaryNormal;
3291         int loc_Texture_SecondaryColor;
3292         int loc_Texture_SecondaryGloss;
3293         int loc_Texture_SecondaryGlow;
3294         int loc_Texture_Pants;
3295         int loc_Texture_Shirt;
3296         int loc_Texture_FogMask;
3297         int loc_Texture_Lightmap;
3298         int loc_Texture_Deluxemap;
3299         int loc_Texture_Attenuation;
3300         int loc_Texture_Cube;
3301         int loc_Texture_Refraction;
3302         int loc_Texture_Reflection;
3303         int loc_Texture_ShadowMapRect;
3304         int loc_Texture_ShadowMapCube;
3305         int loc_Texture_ShadowMap2D;
3306         int loc_Texture_CubeProjection;
3307         int loc_Texture_ScreenDepth;
3308         int loc_Texture_ScreenNormalMap;
3309         int loc_Texture_ScreenDiffuse;
3310         int loc_Texture_ScreenSpecular;
3311         int loc_Alpha;
3312         int loc_BloomBlur_Parameters;
3313         int loc_ClientTime;
3314         int loc_Color_Ambient;
3315         int loc_Color_Diffuse;
3316         int loc_Color_Specular;
3317         int loc_Color_Glow;
3318         int loc_Color_Pants;
3319         int loc_Color_Shirt;
3320         int loc_DeferredColor_Ambient;
3321         int loc_DeferredColor_Diffuse;
3322         int loc_DeferredColor_Specular;
3323         int loc_DeferredMod_Diffuse;
3324         int loc_DeferredMod_Specular;
3325         int loc_DistortScaleRefractReflect;
3326         int loc_EyePosition;
3327         int loc_FogColor;
3328         int loc_FogHeightFade;
3329         int loc_FogPlane;
3330         int loc_FogPlaneViewDist;
3331         int loc_FogRangeRecip;
3332         int loc_LightColor;
3333         int loc_LightDir;
3334         int loc_LightPosition;
3335         int loc_OffsetMapping_Scale;
3336         int loc_PixelSize;
3337         int loc_ReflectColor;
3338         int loc_ReflectFactor;
3339         int loc_ReflectOffset;
3340         int loc_RefractColor;
3341         int loc_Saturation;
3342         int loc_ScreenCenterRefractReflect;
3343         int loc_ScreenScaleRefractReflect;
3344         int loc_ScreenToDepth;
3345         int loc_ShadowMap_Parameters;
3346         int loc_ShadowMap_TextureScale;
3347         int loc_SpecularPower;
3348         int loc_UserVec1;
3349         int loc_UserVec2;
3350         int loc_UserVec3;
3351         int loc_UserVec4;
3352         int loc_ViewTintColor;
3353         int loc_ViewToLight;
3354         int loc_ModelToLight;
3355         int loc_TexMatrix;
3356         int loc_BackgroundTexMatrix;
3357         int loc_ModelViewProjectionMatrix;
3358         int loc_ModelViewMatrix;
3359         int loc_PixelToScreenTexCoord;
3360 }
3361 r_glsl_permutation_t;
3362
3363 #define SHADERPERMUTATION_HASHSIZE 256
3364
3365 /// information about each possible shader permutation
3366 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3367 /// currently selected permutation
3368 r_glsl_permutation_t *r_glsl_permutation;
3369 /// storage for permutations linked in the hash table
3370 memexpandablearray_t r_glsl_permutationarray;
3371
3372 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3373 {
3374         //unsigned int hashdepth = 0;
3375         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3376         r_glsl_permutation_t *p;
3377         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3378         {
3379                 if (p->mode == mode && p->permutation == permutation)
3380                 {
3381                         //if (hashdepth > 10)
3382                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3383                         return p;
3384                 }
3385                 //hashdepth++;
3386         }
3387         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3388         p->mode = mode;
3389         p->permutation = permutation;
3390         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3391         r_glsl_permutationhash[mode][hashindex] = p;
3392         //if (hashdepth > 10)
3393         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3394         return p;
3395 }
3396
3397 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3398 {
3399         char *shaderstring;
3400         if (!filename || !filename[0])
3401                 return NULL;
3402         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3403         if (shaderstring)
3404         {
3405                 if (printfromdisknotice)
3406                         Con_DPrintf("from disk %s... ", filename);
3407                 return shaderstring;
3408         }
3409         else if (!strcmp(filename, "glsl/default.glsl"))
3410         {
3411                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3412                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3413         }
3414         return shaderstring;
3415 }
3416
3417 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3418 {
3419         int i;
3420         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3421         int vertstrings_count = 0;
3422         int geomstrings_count = 0;
3423         int fragstrings_count = 0;
3424         char *vertexstring, *geometrystring, *fragmentstring;
3425         const char *vertstrings_list[32+3];
3426         const char *geomstrings_list[32+3];
3427         const char *fragstrings_list[32+3];
3428         char permutationname[256];
3429
3430         if (p->compiled)
3431                 return;
3432         p->compiled = true;
3433         p->program = 0;
3434
3435         permutationname[0] = 0;
3436         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3437         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3438         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3439
3440         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3441
3442         // the first pretext is which type of shader to compile as
3443         // (later these will all be bound together as a program object)
3444         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3445         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3446         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3447
3448         // the second pretext is the mode (for example a light source)
3449         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3450         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3451         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3452         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3453
3454         // now add all the permutation pretexts
3455         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3456         {
3457                 if (permutation & (1<<i))
3458                 {
3459                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3460                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3461                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3462                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3463                 }
3464                 else
3465                 {
3466                         // keep line numbers correct
3467                         vertstrings_list[vertstrings_count++] = "\n";
3468                         geomstrings_list[geomstrings_count++] = "\n";
3469                         fragstrings_list[fragstrings_count++] = "\n";
3470                 }
3471         }
3472
3473         // now append the shader text itself
3474         vertstrings_list[vertstrings_count++] = vertexstring;
3475         geomstrings_list[geomstrings_count++] = geometrystring;
3476         fragstrings_list[fragstrings_count++] = fragmentstring;
3477
3478         // if any sources were NULL, clear the respective list
3479         if (!vertexstring)
3480                 vertstrings_count = 0;
3481         if (!geometrystring)
3482                 geomstrings_count = 0;
3483         if (!fragmentstring)
3484                 fragstrings_count = 0;
3485
3486         // compile the shader program
3487         if (vertstrings_count + geomstrings_count + fragstrings_count)
3488                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3489         if (p->program)
3490         {
3491                 CHECKGLERROR
3492                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3493                 // look up all the uniform variable names we care about, so we don't
3494                 // have to look them up every time we set them
3495
3496                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3497                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3498                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3499                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3500                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3501                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3502                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3503                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3504                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3505                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3506                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3507                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3508                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3509                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3510                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3511                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3512                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3513                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3514                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3515                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3516                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3517                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3518                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3519                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3520                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3521                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3522                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3523                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3524                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3525                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3526                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3527                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3528                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3529                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3530                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3531                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3532                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3533                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3534                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3535                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3536                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3537                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3538                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3539                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3540                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3541                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3542                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3543                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3544                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3545                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3546                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3547                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3548                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3549                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3550                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3551                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3552                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3553                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3554                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3555                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3556                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3557                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3558                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3559                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3560                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3561                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3562                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3563                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3564                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3565                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3566                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3567                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3568                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3569                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3570                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3571                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3572                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3573                 // initialize the samplers to refer to the texture units we use
3574                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3575                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3576                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3577                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3578                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3579                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3580                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3581                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3582                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3583                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3584                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3585                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3586                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3587                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3588                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3589                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3590                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3591                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3592                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3593                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3594                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3595                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3596                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3597                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3598                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3599                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3600                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3601                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3602                 CHECKGLERROR
3603                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3604         }
3605         else
3606                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3607
3608         // free the strings
3609         if (vertexstring)
3610                 Mem_Free(vertexstring);
3611         if (geometrystring)
3612                 Mem_Free(geometrystring);
3613         if (fragmentstring)
3614                 Mem_Free(fragmentstring);
3615 }
3616
3617 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3618 {
3619         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3620         if (r_glsl_permutation != perm)
3621         {
3622                 r_glsl_permutation = perm;
3623                 if (!r_glsl_permutation->program)
3624                 {
3625                         if (!r_glsl_permutation->compiled)
3626                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3627                         if (!r_glsl_permutation->program)
3628                         {
3629                                 // remove features until we find a valid permutation
3630                                 int i;
3631                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3632                                 {
3633                                         // reduce i more quickly whenever it would not remove any bits
3634                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3635                                         if (!(permutation & j))
3636                                                 continue;
3637                                         permutation -= j;
3638                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3639                                         if (!r_glsl_permutation->compiled)
3640                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3641                                         if (r_glsl_permutation->program)
3642                                                 break;
3643                                 }
3644                                 if (i >= SHADERPERMUTATION_COUNT)
3645                                 {
3646                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3647                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3648                                         qglUseProgramObjectARB(0);CHECKGLERROR
3649                                         return; // no bit left to clear, entire mode is broken
3650                                 }
3651                         }
3652                 }
3653                 CHECKGLERROR
3654                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3655         }
3656         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3657         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3658 }
3659
3660 #ifdef SUPPORTCG
3661 #include <Cg/cgGL.h>
3662 struct r_cg_permutation_s;
3663 typedef struct r_cg_permutation_s
3664 {
3665         /// hash lookup data
3666         struct r_cg_permutation_s *hashnext;
3667         unsigned int mode;
3668         unsigned int permutation;
3669
3670         /// indicates if we have tried compiling this permutation already
3671         qboolean compiled;
3672         /// 0 if compilation failed
3673         CGprogram vprogram;
3674         CGprogram fprogram;
3675         /// locations of detected parameters in programs, or NULL if not found
3676         CGparameter vp_EyePosition;
3677         CGparameter vp_FogPlane;
3678         CGparameter vp_LightDir;
3679         CGparameter vp_LightPosition;
3680         CGparameter vp_ModelToLight;
3681         CGparameter vp_TexMatrix;
3682         CGparameter vp_BackgroundTexMatrix;
3683         CGparameter vp_ModelViewProjectionMatrix;
3684         CGparameter vp_ModelViewMatrix;
3685
3686         CGparameter fp_Texture_First;
3687         CGparameter fp_Texture_Second;
3688         CGparameter fp_Texture_GammaRamps;
3689         CGparameter fp_Texture_Normal;
3690         CGparameter fp_Texture_Color;
3691         CGparameter fp_Texture_Gloss;
3692         CGparameter fp_Texture_Glow;
3693         CGparameter fp_Texture_SecondaryNormal;
3694         CGparameter fp_Texture_SecondaryColor;
3695         CGparameter fp_Texture_SecondaryGloss;
3696         CGparameter fp_Texture_SecondaryGlow;
3697         CGparameter fp_Texture_Pants;
3698         CGparameter fp_Texture_Shirt;
3699         CGparameter fp_Texture_FogMask;
3700         CGparameter fp_Texture_Lightmap;
3701         CGparameter fp_Texture_Deluxemap;
3702         CGparameter fp_Texture_Attenuation;
3703         CGparameter fp_Texture_Cube;
3704         CGparameter fp_Texture_Refraction;
3705         CGparameter fp_Texture_Reflection;
3706         CGparameter fp_Texture_ShadowMapRect;
3707         CGparameter fp_Texture_ShadowMapCube;
3708         CGparameter fp_Texture_ShadowMap2D;
3709         CGparameter fp_Texture_CubeProjection;
3710         CGparameter fp_Texture_ScreenDepth;
3711         CGparameter fp_Texture_ScreenNormalMap;
3712         CGparameter fp_Texture_ScreenDiffuse;
3713         CGparameter fp_Texture_ScreenSpecular;
3714         CGparameter fp_Alpha;
3715         CGparameter fp_BloomBlur_Parameters;
3716         CGparameter fp_ClientTime;
3717         CGparameter fp_Color_Ambient;
3718         CGparameter fp_Color_Diffuse;
3719         CGparameter fp_Color_Specular;
3720         CGparameter fp_Color_Glow;
3721         CGparameter fp_Color_Pants;
3722         CGparameter fp_Color_Shirt;
3723         CGparameter fp_DeferredColor_Ambient;
3724         CGparameter fp_DeferredColor_Diffuse;
3725         CGparameter fp_DeferredColor_Specular;
3726         CGparameter fp_DeferredMod_Diffuse;
3727         CGparameter fp_DeferredMod_Specular;
3728         CGparameter fp_DistortScaleRefractReflect;
3729         CGparameter fp_EyePosition;
3730         CGparameter fp_FogColor;
3731         CGparameter fp_FogHeightFade;
3732         CGparameter fp_FogPlane;
3733         CGparameter fp_FogPlaneViewDist;
3734         CGparameter fp_FogRangeRecip;
3735         CGparameter fp_LightColor;
3736         CGparameter fp_LightDir;
3737         CGparameter fp_LightPosition;
3738         CGparameter fp_OffsetMapping_Scale;
3739         CGparameter fp_PixelSize;
3740         CGparameter fp_ReflectColor;
3741         CGparameter fp_ReflectFactor;
3742         CGparameter fp_ReflectOffset;
3743         CGparameter fp_RefractColor;
3744         CGparameter fp_Saturation;
3745         CGparameter fp_ScreenCenterRefractReflect;
3746         CGparameter fp_ScreenScaleRefractReflect;
3747         CGparameter fp_ScreenToDepth;
3748         CGparameter fp_ShadowMap_Parameters;
3749         CGparameter fp_ShadowMap_TextureScale;
3750         CGparameter fp_SpecularPower;
3751         CGparameter fp_UserVec1;
3752         CGparameter fp_UserVec2;
3753         CGparameter fp_UserVec3;
3754         CGparameter fp_UserVec4;
3755         CGparameter fp_ViewTintColor;
3756         CGparameter fp_ViewToLight;
3757         CGparameter fp_PixelToScreenTexCoord;
3758 }
3759 r_cg_permutation_t;
3760
3761 /// information about each possible shader permutation
3762 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3763 /// currently selected permutation
3764 r_cg_permutation_t *r_cg_permutation;
3765 /// storage for permutations linked in the hash table
3766 memexpandablearray_t r_cg_permutationarray;
3767
3768 #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));}}
3769
3770 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3771 {
3772         //unsigned int hashdepth = 0;
3773         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3774         r_cg_permutation_t *p;
3775         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3776         {
3777                 if (p->mode == mode && p->permutation == permutation)
3778                 {
3779                         //if (hashdepth > 10)
3780                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3781                         return p;
3782                 }
3783                 //hashdepth++;
3784         }
3785         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3786         p->mode = mode;
3787         p->permutation = permutation;
3788         p->hashnext = r_cg_permutationhash[mode][hashindex];
3789         r_cg_permutationhash[mode][hashindex] = p;
3790         //if (hashdepth > 10)
3791         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3792         return p;
3793 }
3794
3795 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3796 {
3797         char *shaderstring;
3798         if (!filename || !filename[0])
3799                 return NULL;
3800         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3801         if (shaderstring)
3802         {
3803                 if (printfromdisknotice)
3804                         Con_DPrintf("from disk %s... ", filename);
3805                 return shaderstring;
3806         }
3807         else if (!strcmp(filename, "cg/default.cg"))
3808         {
3809                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3810                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3811         }
3812         return shaderstring;
3813 }
3814
3815 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3816 {
3817         int i;
3818         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3819         int vertstrings_count = 0, vertstring_length = 0;
3820         int geomstrings_count = 0, geomstring_length = 0;
3821         int fragstrings_count = 0, fragstring_length = 0;
3822         char *t;
3823         char *vertexstring, *geometrystring, *fragmentstring;
3824         char *vertstring, *geomstring, *fragstring;
3825         const char *vertstrings_list[32+3];
3826         const char *geomstrings_list[32+3];
3827         const char *fragstrings_list[32+3];
3828         char permutationname[256];
3829         CGprofile vertexProfile;
3830         CGprofile fragmentProfile;
3831
3832         if (p->compiled)
3833                 return;
3834         p->compiled = true;
3835         p->vprogram = NULL;
3836         p->fprogram = NULL;
3837
3838         permutationname[0] = 0;
3839         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3840         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3841         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3842
3843         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3844
3845         // the first pretext is which type of shader to compile as
3846         // (later these will all be bound together as a program object)
3847         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3848         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3849         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3850
3851         // the second pretext is the mode (for example a light source)
3852         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3853         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3854         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3855         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3856
3857         // now add all the permutation pretexts
3858         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3859         {
3860                 if (permutation & (1<<i))
3861                 {
3862                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3863                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3864                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3865                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3866                 }
3867                 else
3868                 {
3869                         // keep line numbers correct
3870                         vertstrings_list[vertstrings_count++] = "\n";
3871                         geomstrings_list[geomstrings_count++] = "\n";
3872                         fragstrings_list[fragstrings_count++] = "\n";
3873                 }
3874         }
3875
3876         // now append the shader text itself
3877         vertstrings_list[vertstrings_count++] = vertexstring;
3878         geomstrings_list[geomstrings_count++] = geometrystring;
3879         fragstrings_list[fragstrings_count++] = fragmentstring;
3880
3881         // if any sources were NULL, clear the respective list
3882         if (!vertexstring)
3883                 vertstrings_count = 0;
3884         if (!geometrystring)
3885                 geomstrings_count = 0;
3886         if (!fragmentstring)
3887                 fragstrings_count = 0;
3888
3889         vertstring_length = 0;
3890         for (i = 0;i < vertstrings_count;i++)
3891                 vertstring_length += strlen(vertstrings_list[i]);
3892         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3893         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3894                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3895
3896         geomstring_length = 0;
3897         for (i = 0;i < geomstrings_count;i++)
3898                 geomstring_length += strlen(geomstrings_list[i]);
3899         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3900         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3901                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3902
3903         fragstring_length = 0;
3904         for (i = 0;i < fragstrings_count;i++)
3905                 fragstring_length += strlen(fragstrings_list[i]);
3906         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3907         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3908                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3909
3910         CHECKGLERROR
3911         CHECKCGERROR
3912         //vertexProfile = CG_PROFILE_ARBVP1;
3913         //fragmentProfile = CG_PROFILE_ARBFP1;
3914         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3915         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3916         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3917         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3918         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3919         CHECKGLERROR
3920
3921         // compile the vertex program
3922         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL)))
3923         {
3924                 CHECKCGERROR
3925 #if 0
3926                 cgCompileProgram(p->vprogram);CHECKCGERROR
3927                 if (!cgIsProgramCompiled(p->vprogram))
3928                 {
3929                         CHECKCGERROR
3930                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3931                         p->vprogram = 0;
3932                 }
3933                 else
3934 #endif
3935                 {
3936                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3937                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3938                         // look up all the uniform variable names we care about, so we don't
3939                         // have to look them up every time we set them
3940                         CHECKCGERROR
3941                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3942                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3943                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3944                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3945                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3946                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3947                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3948                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3949                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3950                         CHECKCGERROR
3951                 }
3952         }
3953
3954         // compile the fragment program
3955         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL)))
3956         {
3957 #if 0
3958                 cgCompileProgram(p->fprogram);CHECKCGERROR
3959                 if (!cgIsProgramCompiled(p->fprogram))
3960                 {
3961                         CHECKCGERROR
3962                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3963                         p->fprogram = 0;
3964                 }
3965                 else
3966 #endif
3967                 {
3968                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3969                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3970                         CHECKCGERROR
3971                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3972                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3973                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3974                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3975                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3976                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3977                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3978                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3979                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3980                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3981                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3982                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3983                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3984                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3985                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3986                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3987                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3988                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3989                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3990                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3991                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3992                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3993                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3994                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3995                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3996                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3997                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3998                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3999                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4000                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4001                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4002                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4003                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4004                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4005                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4006                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4007                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4008                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4009                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4010                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4011                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4012                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4013                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4014                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4015                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4016                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4017                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4018                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4019                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4020                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4021                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4022                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4023                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4024                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4025                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4026                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4027                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4028                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4029                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4030                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4031                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4032                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4033                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4034                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4035                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4036                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4037                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4038                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4039                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4040                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4041                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4042                         p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4043                         CHECKCGERROR
4044                 }
4045         }
4046
4047         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4048                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4049         else
4050                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4051
4052         // free the strings
4053         if (vertstring)
4054                 Mem_Free(vertstring);
4055         if (geomstring)
4056                 Mem_Free(geomstring);
4057         if (fragstring)
4058                 Mem_Free(fragstring);
4059         if (vertexstring)
4060                 Mem_Free(vertexstring);
4061         if (geometrystring)
4062                 Mem_Free(geometrystring);
4063         if (fragmentstring)
4064                 Mem_Free(fragmentstring);
4065 }
4066
4067 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4068 {
4069         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4070         CHECKGLERROR
4071         CHECKCGERROR
4072         if (r_cg_permutation != perm)
4073         {
4074                 r_cg_permutation = perm;
4075                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4076                 {
4077                         if (!r_cg_permutation->compiled)
4078                                 R_CG_CompilePermutation(perm, mode, permutation);
4079                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4080                         {
4081                                 // remove features until we find a valid permutation
4082                                 int i;
4083                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4084                                 {
4085                                         // reduce i more quickly whenever it would not remove any bits
4086                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4087                                         if (!(permutation & j))
4088                                                 continue;
4089                                         permutation -= j;
4090                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4091                                         if (!r_cg_permutation->compiled)
4092                                                 R_CG_CompilePermutation(perm, mode, permutation);
4093                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4094                                                 break;
4095                                 }
4096                                 if (i >= SHADERPERMUTATION_COUNT)
4097                                 {
4098                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4099                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4100                                         return; // no bit left to clear, entire mode is broken
4101                                 }
4102                         }
4103                 }
4104                 CHECKGLERROR
4105                 CHECKCGERROR
4106                 if (r_cg_permutation->vprogram)
4107                 {
4108                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4109                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4110                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4111                 }
4112                 else
4113                 {
4114                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4115                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4116                 }
4117                 if (r_cg_permutation->fprogram)
4118                 {
4119                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4120                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4121                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4122                 }
4123                 else
4124                 {
4125                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4126                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4127                 }
4128         }
4129         CHECKCGERROR
4130         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4131         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4132 }
4133
4134 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4135 {
4136         cgGLSetTextureParameter(param, R_GetTexture(tex));
4137         cgGLEnableTextureParameter(param);
4138 }
4139 #endif
4140
4141 void R_GLSL_Restart_f(void)
4142 {
4143         unsigned int i, limit;
4144         switch(vid.renderpath)
4145         {
4146         case RENDERPATH_GL20:
4147                 {
4148                         r_glsl_permutation_t *p;
4149                         r_glsl_permutation = NULL;
4150                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4151                         for (i = 0;i < limit;i++)
4152                         {
4153                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4154                                 {
4155                                         GL_Backend_FreeProgram(p->program);
4156                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4157                                 }
4158                         }
4159                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4160                 }
4161                 break;
4162         case RENDERPATH_CGGL:
4163 #ifdef SUPPORTCG
4164                 {
4165                         r_cg_permutation_t *p;
4166                         r_cg_permutation = NULL;
4167                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4168                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4169                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4170                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4171                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4172                         for (i = 0;i < limit;i++)
4173                         {
4174                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4175                                 {
4176                                         if (p->vprogram)
4177                                                 cgDestroyProgram(p->vprogram);
4178                                         if (p->fprogram)
4179                                                 cgDestroyProgram(p->fprogram);
4180                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4181                                 }
4182                         }
4183                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4184                 }
4185                 break;
4186 #endif
4187         case RENDERPATH_GL13:
4188         case RENDERPATH_GL11:
4189                 break;
4190         }
4191 }
4192
4193 void R_GLSL_DumpShader_f(void)
4194 {
4195         int i;
4196         qfile_t *file;
4197
4198         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4199         if (file)
4200         {
4201                 FS_Print(file, "/* The engine may define the following macros:\n");
4202                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4203                 for (i = 0;i < SHADERMODE_COUNT;i++)
4204                         FS_Print(file, glslshadermodeinfo[i].pretext);
4205                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4206                         FS_Print(file, shaderpermutationinfo[i].pretext);
4207                 FS_Print(file, "*/\n");
4208                 FS_Print(file, builtinshaderstring);
4209                 FS_Close(file);
4210                 Con_Printf("glsl/default.glsl written\n");
4211         }
4212         else
4213                 Con_Printf("failed to write to glsl/default.glsl\n");
4214
4215 #ifdef SUPPORTCG
4216         file = FS_OpenRealFile("cg/default.cg", "w", false);
4217         if (file)
4218         {
4219                 FS_Print(file, "/* The engine may define the following macros:\n");
4220                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4221                 for (i = 0;i < SHADERMODE_COUNT;i++)
4222                         FS_Print(file, cgshadermodeinfo[i].pretext);
4223                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4224                         FS_Print(file, shaderpermutationinfo[i].pretext);
4225                 FS_Print(file, "*/\n");
4226                 FS_Print(file, builtincgshaderstring);
4227                 FS_Close(file);
4228                 Con_Printf("cg/default.cg written\n");
4229         }
4230         else
4231                 Con_Printf("failed to write to cg/default.cg\n");
4232 #endif
4233 }
4234
4235 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4236 {
4237         if (!second)
4238                 texturemode = GL_MODULATE;
4239         switch (vid.renderpath)
4240         {
4241         case RENDERPATH_GL20:
4242                 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))));
4243                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4244                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4245                 break;
4246         case RENDERPATH_CGGL:
4247 #ifdef SUPPORTCG
4248                 CHECKCGERROR
4249                 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))));
4250                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4251                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4252 #endif
4253                 break;
4254         case RENDERPATH_GL13:
4255                 R_Mesh_TexBind(0, first );
4256                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4257                 R_Mesh_TexBind(1, second);
4258                 if (second)
4259                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4260                 break;
4261         case RENDERPATH_GL11:
4262                 R_Mesh_TexBind(0, first );
4263                 break;
4264         }
4265 }
4266
4267 void R_SetupShader_DepthOrShadow(void)
4268 {
4269         switch (vid.renderpath)
4270         {
4271         case RENDERPATH_GL20:
4272                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4273                 break;
4274         case RENDERPATH_CGGL:
4275 #ifdef SUPPORTCG
4276                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4277 #endif
4278                 break;
4279         case RENDERPATH_GL13:
4280                 R_Mesh_TexBind(0, 0);
4281                 R_Mesh_TexBind(1, 0);
4282                 break;
4283         case RENDERPATH_GL11:
4284                 R_Mesh_TexBind(0, 0);
4285                 break;
4286         }
4287 }
4288
4289 void R_SetupShader_ShowDepth(void)
4290 {
4291         switch (vid.renderpath)
4292         {
4293         case RENDERPATH_GL20:
4294                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4295                 break;
4296         case RENDERPATH_CGGL:
4297 #ifdef SUPPORTCG
4298                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4299 #endif
4300                 break;
4301         case RENDERPATH_GL13:
4302                 break;
4303         case RENDERPATH_GL11:
4304                 break;
4305         }
4306 }
4307
4308 extern qboolean r_shadow_usingdeferredprepass;
4309 extern cvar_t r_shadow_deferred_8bitrange;
4310 extern rtexture_t *r_shadow_attenuationgradienttexture;
4311 extern rtexture_t *r_shadow_attenuation2dtexture;
4312 extern rtexture_t *r_shadow_attenuation3dtexture;
4313 extern qboolean r_shadow_usingshadowmaprect;
4314 extern qboolean r_shadow_usingshadowmapcube;
4315 extern qboolean r_shadow_usingshadowmap2d;
4316 extern float r_shadow_shadowmap_texturescale[2];
4317 extern float r_shadow_shadowmap_parameters[4];
4318 extern qboolean r_shadow_shadowmapvsdct;
4319 extern qboolean r_shadow_shadowmapsampler;
4320 extern int r_shadow_shadowmappcf;
4321 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4322 extern rtexture_t *r_shadow_shadowmap2dtexture;
4323 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4324 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4325 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4326 extern int r_shadow_prepass_width;
4327 extern int r_shadow_prepass_height;
4328 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4329 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4330 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4331 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4332 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4333 {
4334         // select a permutation of the lighting shader appropriate to this
4335         // combination of texture, entity, light source, and fogging, only use the
4336         // minimum features necessary to avoid wasting rendering time in the
4337         // fragment shader on features that are not being used
4338         unsigned int permutation = 0;
4339         unsigned int mode = 0;
4340         float m16f[16];
4341         // TODO: implement geometry-shader based shadow volumes someday
4342         if (r_glsl_offsetmapping.integer)
4343         {
4344                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4345                 if (r_glsl_offsetmapping_reliefmapping.integer)
4346                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4347         }
4348         if (rsurfacepass == RSURFPASS_BACKGROUND)
4349         {
4350                 // distorted background
4351                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4352                         mode = SHADERMODE_WATER;
4353                 else
4354                         mode = SHADERMODE_REFRACTION;
4355         }
4356         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4357         {
4358                 // normalmap (deferred prepass), may use alpha test on diffuse
4359                 mode = SHADERMODE_DEFERREDGEOMETRY;
4360                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4361                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4362                 if (r_glsl_offsetmapping.integer)
4363                 {
4364                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4365                         if (r_glsl_offsetmapping_reliefmapping.integer)
4366                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4367                 }
4368         }
4369         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4370         {
4371                 // light source
4372                 mode = SHADERMODE_LIGHTSOURCE;
4373                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4374                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4375                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4376                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4377                 if (diffusescale > 0)
4378                         permutation |= SHADERPERMUTATION_DIFFUSE;
4379                 if (specularscale > 0)
4380                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4381                 if (r_refdef.fogenabled)
4382                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4383                 if (rsurface.texture->colormapping)
4384                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4385                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4386                 {
4387                         if (r_shadow_usingshadowmaprect)
4388                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4389                         if (r_shadow_usingshadowmap2d)
4390                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4391                         if (r_shadow_usingshadowmapcube)
4392                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4393                         else if(r_shadow_shadowmapvsdct)
4394                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4395
4396                         if (r_shadow_shadowmapsampler)
4397                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4398                         if (r_shadow_shadowmappcf > 1)
4399                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4400                         else if (r_shadow_shadowmappcf)
4401                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4402                 }
4403         }
4404         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4405         {
4406                 // unshaded geometry (fullbright or ambient model lighting)
4407                 mode = SHADERMODE_FLATCOLOR;
4408                 ambientscale = diffusescale = specularscale = 0;
4409                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4410                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4411                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4412                         permutation |= SHADERPERMUTATION_GLOW;
4413                 if (r_refdef.fogenabled)
4414                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4415                 if (rsurface.texture->colormapping)
4416                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4417                 if (r_glsl_offsetmapping.integer)
4418                 {
4419                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4420                         if (r_glsl_offsetmapping_reliefmapping.integer)
4421                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4422                 }
4423                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4424                         permutation |= SHADERPERMUTATION_REFLECTION;
4425         }
4426         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4427         {
4428                 // directional model lighting
4429                 mode = SHADERMODE_LIGHTDIRECTION;
4430                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4431                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4432                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4433                         permutation |= SHADERPERMUTATION_GLOW;
4434                 permutation |= SHADERPERMUTATION_DIFFUSE;
4435                 if (specularscale > 0)
4436                         permutation |= SHADERPERMUTATION_SPECULAR;
4437                 if (r_refdef.fogenabled)
4438                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4439                 if (rsurface.texture->colormapping)
4440                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4442                         permutation |= SHADERPERMUTATION_REFLECTION;
4443                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4444                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4445         }
4446         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4447         {
4448                 // ambient model lighting
4449                 mode = SHADERMODE_LIGHTDIRECTION;
4450                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4451                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4452                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4453                         permutation |= SHADERPERMUTATION_GLOW;
4454                 if (r_refdef.fogenabled)
4455                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4456                 if (rsurface.texture->colormapping)
4457                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4458                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4459                         permutation |= SHADERPERMUTATION_REFLECTION;
4460                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4461                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4462         }
4463         else
4464         {
4465                 // lightmapped wall
4466                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4467                 {
4468                         // deluxemapping (light direction texture)
4469                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4470                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4471                         else
4472                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4473                         permutation |= SHADERPERMUTATION_DIFFUSE;
4474                         if (specularscale > 0)
4475                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4476                 }
4477                 else if (r_glsl_deluxemapping.integer >= 2)
4478                 {
4479                         // fake deluxemapping (uniform light direction in tangentspace)
4480                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4481                         permutation |= SHADERPERMUTATION_DIFFUSE;
4482                         if (specularscale > 0)
4483                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4484                 }
4485                 else if (rsurface.uselightmaptexture)
4486                 {
4487                         // ordinary lightmapping (q1bsp, q3bsp)
4488                         mode = SHADERMODE_LIGHTMAP;
4489                 }
4490                 else
4491                 {
4492                         // ordinary vertex coloring (q3bsp)
4493                         mode = SHADERMODE_VERTEXCOLOR;
4494                 }
4495                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4496                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4497                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4498                         permutation |= SHADERPERMUTATION_GLOW;
4499                 if (r_refdef.fogenabled)
4500                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4501                 if (rsurface.texture->colormapping)
4502                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4503                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4504                         permutation |= SHADERPERMUTATION_REFLECTION;
4505                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4506                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4507         }
4508         if(permutation & SHADERPERMUTATION_SPECULAR)
4509                 if(r_shadow_glossexact.integer)
4510                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4511         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
4512                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4513         switch(vid.renderpath)
4514         {
4515         case RENDERPATH_GL20:
4516                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4517                 if (mode == SHADERMODE_LIGHTSOURCE)
4518                 {
4519                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4520                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4521                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4522                         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);
4523                         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);
4524                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
4525         
4526                         // additive passes are only darkened by fog, not tinted
4527                         if (r_glsl_permutation->loc_FogColor >= 0)
4528                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4529                         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]);
4530                         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]);
4531                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4532                 }
4533                 else
4534                 {
4535                         if (mode == SHADERMODE_FLATCOLOR)
4536                         {
4537                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4538                         }
4539                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4540                         {
4541                                 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]);
4542                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
4543                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4544                                 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);
4545                                 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);
4546                                 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]);
4547                                 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]);
4548                         }
4549                         else
4550                         {
4551                                 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]);
4552                                 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]);
4553                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4554                                 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);
4555                                 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);
4556                         }
4557                         // additive passes are only darkened by fog, not tinted
4558                         if (r_glsl_permutation->loc_FogColor >= 0)
4559                         {
4560                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4561                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4562                                 else
4563                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4564                         }
4565                         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);
4566                         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]);
4567                         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]);
4568                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4569                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4570                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4571                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4572                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4573                 }
4574                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4575                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4576                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4577                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4578                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4579                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4580                 {
4581                         if (rsurface.texture->pantstexture)
4582                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4583                         else
4584                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4585                 }
4586                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4587                 {
4588                         if (rsurface.texture->shirttexture)
4589                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4590                         else
4591                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4592                 }
4593                 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]);
4594                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4595                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4596                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4597                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4598                 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]);
4599                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4600
4601         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4602         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4603         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4604                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4605                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4606                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4607                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4608                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4609                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4610                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4611                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4612                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4613                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4614                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4615                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4616                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4617                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4618                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4619                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4620                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4621                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4622                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4623                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4624                 if (rsurface.rtlight)
4625                 {
4626                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4627                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4628                         if (r_shadow_usingshadowmapcube)
4629                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4630                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4631                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4632                 }
4633                 CHECKGLERROR
4634                 break;
4635         case RENDERPATH_CGGL:
4636 #ifdef SUPPORTCG
4637                 R_SetupShader_SetPermutationCG(mode, permutation);
4638                 if (mode == SHADERMODE_LIGHTSOURCE)
4639                 {
4640                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4641                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4642                 }
4643                 else
4644                 {
4645                         if (mode == SHADERMODE_LIGHTDIRECTION)
4646                         {
4647                                 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
4648                         }
4649                 }
4650                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4651                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4652                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4653                 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
4654                 CHECKGLERROR
4655
4656                 if (mode == SHADERMODE_LIGHTSOURCE)
4657                 {
4658                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4659                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4660                         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
4661                         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
4662                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
4663
4664                         // additive passes are only darkened by fog, not tinted
4665                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4666                         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
4667                         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
4668                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4669                 }
4670                 else
4671                 {
4672                         if (mode == SHADERMODE_FLATCOLOR)
4673                         {
4674                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4675                         }
4676                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4677                         {
4678                                 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
4679                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
4680                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
4681                                 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
4682                                 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
4683                                 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
4684                                 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
4685                         }
4686                         else
4687                         {
4688                                 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
4689                                 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
4690                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
4691                                 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
4692                                 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
4693                         }
4694                         // additive passes are only darkened by fog, not tinted
4695                         if (r_cg_permutation->fp_FogColor)
4696                         {
4697                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4698                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4699                                 else
4700                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4701                                 CHECKCGERROR
4702                         }
4703                         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
4704                         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
4705                         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
4706                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4707                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4708                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4709                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4710                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4711                 }
4712                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4713                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4714                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4715                 if (r_cg_permutation->fp_Color_Pants)
4716                 {
4717                         if (rsurface.texture->pantstexture)
4718                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4719                         else
4720                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4721                         CHECKCGERROR
4722                 }
4723                 if (r_cg_permutation->fp_Color_Shirt)
4724                 {
4725                         if (rsurface.texture->shirttexture)
4726                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4727                         else
4728                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4729                         CHECKCGERROR
4730                 }
4731                 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
4732                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4733                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4734                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4735                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4736                 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
4737                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
4738
4739         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
4740         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
4741         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
4742                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
4743                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
4744                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
4745                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
4746                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
4747                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
4748                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
4749                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
4750                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
4751                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
4752                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
4753                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
4754                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
4755                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4756                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
4757                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
4758                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4759                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4760                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
4761                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
4762                 if (rsurface.rtlight)
4763                 {
4764                         if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4765                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4766                         if (r_shadow_usingshadowmapcube)
4767                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4768                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4769                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4770                 }
4771
4772                 CHECKGLERROR
4773 #endif
4774                 break;
4775         case RENDERPATH_GL13:
4776         case RENDERPATH_GL11:
4777                 break;
4778         }
4779 }
4780
4781 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4782 {
4783         // select a permutation of the lighting shader appropriate to this
4784         // combination of texture, entity, light source, and fogging, only use the
4785         // minimum features necessary to avoid wasting rendering time in the
4786         // fragment shader on features that are not being used
4787         unsigned int permutation = 0;
4788         unsigned int mode = 0;
4789         const float *lightcolorbase = rtlight->currentcolor;
4790         float ambientscale = rtlight->ambientscale;
4791         float diffusescale = rtlight->diffusescale;
4792         float specularscale = rtlight->specularscale;
4793         // this is the location of the light in view space
4794         vec3_t viewlightorigin;
4795         // this transforms from view space (camera) to light space (cubemap)
4796         matrix4x4_t viewtolight;
4797         matrix4x4_t lighttoview;
4798         float viewtolight16f[16];
4799         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4800         // light source
4801         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4802         if (rtlight->currentcubemap != r_texture_whitecube)
4803                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4804         if (diffusescale > 0)
4805                 permutation |= SHADERPERMUTATION_DIFFUSE;
4806         if (specularscale > 0)
4807         {
4808                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4809                 if (r_shadow_glossexact.integer)
4810                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4811         }
4812         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4813         {
4814                 if (r_shadow_usingshadowmaprect)
4815                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4816                 if (r_shadow_usingshadowmap2d)
4817                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4818                 if (r_shadow_usingshadowmapcube)
4819                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4820                 else if(r_shadow_shadowmapvsdct)
4821                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4822
4823                 if (r_shadow_shadowmapsampler)
4824                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4825                 if (r_shadow_shadowmappcf > 1)
4826                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4827                 else if (r_shadow_shadowmappcf)
4828                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4829         }
4830         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4831         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4832         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4833         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4834         switch(vid.renderpath)
4835         {
4836         case RENDERPATH_GL20:
4837                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4838                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4839                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4840                 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);
4841                 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);
4842                 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);
4843                 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]);
4844                 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]);
4845                 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));
4846                 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]);
4847                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4848
4849                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
4850                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
4851                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
4852                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
4853                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
4854                 if (r_shadow_usingshadowmapcube)
4855                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4856                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
4857                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
4858                 break;
4859         case RENDERPATH_CGGL:
4860 #ifdef SUPPORTCG
4861                 R_SetupShader_SetPermutationCG(mode, permutation);
4862                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4863                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4864                 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
4865                 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
4866                 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
4867                 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
4868                 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
4869                 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
4870                 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
4871                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
4872
4873                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4874                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4875                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4876                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4877                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4878                 if (r_shadow_usingshadowmapcube)
4879                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4880                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4881                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4882 #endif
4883                 break;
4884         case RENDERPATH_GL13:
4885         case RENDERPATH_GL11:
4886                 break;
4887         }
4888 }
4889
4890 #define SKINFRAME_HASH 1024
4891
4892 typedef struct
4893 {
4894         int loadsequence; // incremented each level change
4895         memexpandablearray_t array;
4896         skinframe_t *hash[SKINFRAME_HASH];
4897 }
4898 r_skinframe_t;
4899 r_skinframe_t r_skinframe;
4900
4901 void R_SkinFrame_PrepareForPurge(void)
4902 {
4903         r_skinframe.loadsequence++;
4904         // wrap it without hitting zero
4905         if (r_skinframe.loadsequence >= 200)
4906                 r_skinframe.loadsequence = 1;
4907 }
4908
4909 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
4910 {
4911         if (!skinframe)
4912                 return;
4913         // mark the skinframe as used for the purging code
4914         skinframe->loadsequence = r_skinframe.loadsequence;
4915 }
4916
4917 void R_SkinFrame_Purge(void)
4918 {
4919         int i;
4920         skinframe_t *s;
4921         for (i = 0;i < SKINFRAME_HASH;i++)
4922         {
4923                 for (s = r_skinframe.hash[i];s;s = s->next)
4924                 {
4925                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
4926                         {
4927                                 if (s->merged == s->base)
4928                                         s->merged = NULL;
4929                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
4930                                 R_PurgeTexture(s->stain );s->stain  = NULL;
4931                                 R_PurgeTexture(s->merged);s->merged = NULL;
4932                                 R_PurgeTexture(s->base  );s->base   = NULL;
4933                                 R_PurgeTexture(s->pants );s->pants  = NULL;
4934                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
4935                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
4936                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
4937                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
4938                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
4939                                 s->loadsequence = 0;
4940                         }
4941                 }
4942         }
4943 }
4944
4945 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
4946         skinframe_t *item;
4947         char basename[MAX_QPATH];
4948
4949         Image_StripImageExtension(name, basename, sizeof(basename));
4950
4951         if( last == NULL ) {
4952                 int hashindex;
4953                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4954                 item = r_skinframe.hash[hashindex];
4955         } else {
4956                 item = last->next;
4957         }
4958
4959         // linearly search through the hash bucket
4960         for( ; item ; item = item->next ) {
4961                 if( !strcmp( item->basename, basename ) ) {
4962                         return item;
4963                 }
4964         }
4965         return NULL;
4966 }
4967
4968 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
4969 {
4970         skinframe_t *item;
4971         int hashindex;
4972         char basename[MAX_QPATH];
4973
4974         Image_StripImageExtension(name, basename, sizeof(basename));
4975
4976         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4977         for (item = r_skinframe.hash[hashindex];item;item = item->next)
4978                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
4979                         break;
4980
4981         if (!item) {
4982                 rtexture_t *dyntexture;
4983                 // check whether its a dynamic texture
4984                 dyntexture = CL_GetDynTexture( basename );
4985                 if (!add && !dyntexture)
4986                         return NULL;
4987                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
4988                 memset(item, 0, sizeof(*item));
4989                 strlcpy(item->basename, basename, sizeof(item->basename));
4990                 item->base = dyntexture; // either NULL or dyntexture handle
4991                 item->textureflags = textureflags;
4992                 item->comparewidth = comparewidth;
4993                 item->compareheight = compareheight;
4994                 item->comparecrc = comparecrc;
4995                 item->next = r_skinframe.hash[hashindex];
4996                 r_skinframe.hash[hashindex] = item;
4997         }
4998         else if( item->base == NULL )
4999         {
5000                 rtexture_t *dyntexture;
5001                 // check whether its a dynamic texture
5002                 // 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]
5003                 dyntexture = CL_GetDynTexture( basename );
5004                 item->base = dyntexture; // either NULL or dyntexture handle
5005         }
5006
5007         R_SkinFrame_MarkUsed(item);
5008         return item;
5009 }
5010
5011 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5012         { \
5013                 unsigned long long avgcolor[5], wsum; \
5014                 int pix, comp, w; \
5015                 avgcolor[0] = 0; \
5016                 avgcolor[1] = 0; \
5017                 avgcolor[2] = 0; \
5018                 avgcolor[3] = 0; \
5019                 avgcolor[4] = 0; \
5020                 wsum = 0; \
5021                 for(pix = 0; pix < cnt; ++pix) \
5022                 { \
5023                         w = 0; \
5024                         for(comp = 0; comp < 3; ++comp) \
5025                                 w += getpixel; \
5026                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5027                         { \
5028                                 ++wsum; \
5029                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5030                                 w = getpixel; \
5031                                 for(comp = 0; comp < 3; ++comp) \
5032                                         avgcolor[comp] += getpixel * w; \
5033                                 avgcolor[3] += w; \
5034                         } \
5035                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5036                         avgcolor[4] += getpixel; \
5037                 } \
5038                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5039                         avgcolor[3] = 1; \
5040                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5041                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5042                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5043                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5044         }
5045
5046 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5047 {
5048         int j;
5049         unsigned char *pixels;
5050         unsigned char *bumppixels;
5051         unsigned char *basepixels = NULL;
5052         int basepixels_width = 0;
5053         int basepixels_height = 0;
5054         skinframe_t *skinframe;
5055         rtexture_t *ddsbase = NULL;
5056         qboolean ddshasalpha = false;
5057         float ddsavgcolor[4];
5058         char basename[MAX_QPATH];
5059
5060         if (cls.state == ca_dedicated)
5061                 return NULL;
5062
5063         // return an existing skinframe if already loaded
5064         // if loading of the first image fails, don't make a new skinframe as it
5065         // would cause all future lookups of this to be missing
5066         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5067         if (skinframe && skinframe->base)
5068                 return skinframe;
5069
5070         Image_StripImageExtension(name, basename, sizeof(basename));
5071
5072         // check for DDS texture file first
5073         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5074         {
5075                 basepixels = loadimagepixelsbgra(name, complain, true);
5076                 if (basepixels == NULL)
5077                         return NULL;
5078         }
5079
5080         if (developer_loading.integer)
5081                 Con_Printf("loading skin \"%s\"\n", name);
5082
5083         // we've got some pixels to store, so really allocate this new texture now
5084         if (!skinframe)
5085                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5086         skinframe->stain = NULL;
5087         skinframe->merged = NULL;
5088         skinframe->base = NULL;
5089         skinframe->pants = NULL;
5090         skinframe->shirt = NULL;
5091         skinframe->nmap = NULL;
5092         skinframe->gloss = NULL;
5093         skinframe->glow = NULL;
5094         skinframe->fog = NULL;
5095         skinframe->hasalpha = false;
5096
5097         if (ddsbase)
5098         {
5099                 skinframe->base = ddsbase;
5100                 skinframe->hasalpha = ddshasalpha;
5101                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5102                 if (r_loadfog && skinframe->hasalpha)
5103                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5104                 //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]);
5105         }
5106         else
5107         {
5108                 basepixels_width = image_width;
5109                 basepixels_height = image_height;
5110                 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);
5111                 if (textureflags & TEXF_ALPHA)
5112                 {
5113                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5114                         {
5115                                 if (basepixels[j] < 255)
5116                                 {
5117                                         skinframe->hasalpha = true;
5118                                         break;
5119                                 }
5120                         }
5121                         if (r_loadfog && skinframe->hasalpha)
5122                         {
5123                                 // has transparent pixels
5124                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5125                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5126                                 {
5127                                         pixels[j+0] = 255;
5128                                         pixels[j+1] = 255;
5129                                         pixels[j+2] = 255;
5130                                         pixels[j+3] = basepixels[j+3];
5131                                 }
5132                                 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);
5133                                 Mem_Free(pixels);
5134                         }
5135                 }
5136                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5137                 //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]);
5138                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5139                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5140                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5141                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5142         }
5143
5144         if (r_loaddds)
5145         {
5146                 if (r_loadnormalmap)
5147                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5148                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5149                 if (r_loadgloss)
5150                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5151                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5152                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5153         }
5154
5155         // _norm is the name used by tenebrae and has been adopted as standard
5156         if (r_loadnormalmap && skinframe->nmap == NULL)
5157         {
5158                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5159                 {
5160                         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);
5161                         Mem_Free(pixels);
5162                         pixels = NULL;
5163                 }
5164                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5165                 {
5166                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5167                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5168                         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);
5169                         Mem_Free(pixels);
5170                         Mem_Free(bumppixels);
5171                 }
5172                 else if (r_shadow_bumpscale_basetexture.value > 0)
5173                 {
5174                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5175                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5176                         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);
5177                         Mem_Free(pixels);
5178                 }
5179                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5180                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5181         }
5182
5183         // _luma is supported only for tenebrae compatibility
5184         // _glow is the preferred name
5185         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5186         {
5187                 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);
5188                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5189                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5190                 Mem_Free(pixels);pixels = NULL;
5191         }
5192
5193         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5194         {
5195                 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);
5196                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5197                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5198                 Mem_Free(pixels);
5199                 pixels = NULL;
5200         }
5201
5202         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5203         {
5204                 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);
5205                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5206                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5207                 Mem_Free(pixels);
5208                 pixels = NULL;
5209         }
5210
5211         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5212         {
5213                 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);
5214                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5215                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5216                 Mem_Free(pixels);
5217                 pixels = NULL;
5218         }
5219
5220         if (basepixels)
5221                 Mem_Free(basepixels);
5222
5223         return skinframe;
5224 }
5225
5226 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5227 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5228 {
5229         int i;
5230         unsigned char *temp1, *temp2;
5231         skinframe_t *skinframe;
5232
5233         if (cls.state == ca_dedicated)
5234                 return NULL;
5235
5236         // if already loaded just return it, otherwise make a new skinframe
5237         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5238         if (skinframe && skinframe->base)
5239                 return skinframe;
5240
5241         skinframe->stain = NULL;
5242         skinframe->merged = NULL;
5243         skinframe->base = NULL;
5244         skinframe->pants = NULL;
5245         skinframe->shirt = NULL;
5246         skinframe->nmap = NULL;
5247         skinframe->gloss = NULL;
5248         skinframe->glow = NULL;
5249         skinframe->fog = NULL;
5250         skinframe->hasalpha = false;
5251
5252         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5253         if (!skindata)
5254                 return NULL;
5255
5256         if (developer_loading.integer)
5257                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5258
5259         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5260         {
5261                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5262                 temp2 = temp1 + width * height * 4;
5263                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5264                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5265                 Mem_Free(temp1);
5266         }
5267         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5268         if (textureflags & TEXF_ALPHA)
5269         {
5270                 for (i = 3;i < width * height * 4;i += 4)
5271                 {
5272                         if (skindata[i] < 255)
5273                         {
5274                                 skinframe->hasalpha = true;
5275                                 break;
5276                         }
5277                 }
5278                 if (r_loadfog && skinframe->hasalpha)
5279                 {
5280                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5281                         memcpy(fogpixels, skindata, width * height * 4);
5282                         for (i = 0;i < width * height * 4;i += 4)
5283                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5284                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5285                         Mem_Free(fogpixels);
5286                 }
5287         }
5288
5289         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5290         //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]);
5291
5292         return skinframe;
5293 }
5294
5295 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5296 {
5297         int i;
5298         int featuresmask;
5299         skinframe_t *skinframe;
5300
5301         if (cls.state == ca_dedicated)
5302                 return NULL;
5303
5304         // if already loaded just return it, otherwise make a new skinframe
5305         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5306         if (skinframe && skinframe->base)
5307                 return skinframe;
5308
5309         skinframe->stain = NULL;
5310         skinframe->merged = NULL;
5311         skinframe->base = NULL;
5312         skinframe->pants = NULL;
5313         skinframe->shirt = NULL;
5314         skinframe->nmap = NULL;
5315         skinframe->gloss = NULL;
5316         skinframe->glow = NULL;
5317         skinframe->fog = NULL;
5318         skinframe->hasalpha = false;
5319
5320         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5321         if (!skindata)
5322                 return NULL;
5323
5324         if (developer_loading.integer)
5325                 Con_Printf("loading quake skin \"%s\"\n", name);
5326
5327         // 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)
5328         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5329         memcpy(skinframe->qpixels, skindata, width*height);
5330         skinframe->qwidth = width;
5331         skinframe->qheight = height;
5332
5333         featuresmask = 0;
5334         for (i = 0;i < width * height;i++)
5335                 featuresmask |= palette_featureflags[skindata[i]];
5336
5337         skinframe->hasalpha = false;
5338         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5339         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5340         skinframe->qgeneratemerged = true;
5341         skinframe->qgeneratebase = skinframe->qhascolormapping;
5342         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5343
5344         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5345         //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]);
5346
5347         return skinframe;
5348 }
5349
5350 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5351 {
5352         int width;
5353         int height;
5354         unsigned char *skindata;
5355
5356         if (!skinframe->qpixels)
5357                 return;
5358
5359         if (!skinframe->qhascolormapping)
5360                 colormapped = false;
5361
5362         if (colormapped)
5363         {
5364                 if (!skinframe->qgeneratebase)
5365                         return;
5366         }
5367         else
5368         {
5369                 if (!skinframe->qgeneratemerged)
5370                         return;
5371         }
5372
5373         width = skinframe->qwidth;
5374         height = skinframe->qheight;
5375         skindata = skinframe->qpixels;
5376
5377         if (skinframe->qgeneratenmap)
5378         {
5379                 unsigned char *temp1, *temp2;
5380                 skinframe->qgeneratenmap = false;
5381                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5382                 temp2 = temp1 + width * height * 4;
5383                 // use either a custom palette or the quake palette
5384                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5385                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5386                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5387                 Mem_Free(temp1);
5388         }
5389
5390         if (skinframe->qgenerateglow)
5391         {
5392                 skinframe->qgenerateglow = false;
5393                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5394         }
5395
5396         if (colormapped)
5397         {
5398                 skinframe->qgeneratebase = false;
5399                 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);
5400                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5401                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5402         }
5403         else
5404         {
5405                 skinframe->qgeneratemerged = false;
5406                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5407         }
5408
5409         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5410         {
5411                 Mem_Free(skinframe->qpixels);
5412                 skinframe->qpixels = NULL;
5413         }
5414 }
5415
5416 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)
5417 {
5418         int i;
5419         skinframe_t *skinframe;
5420
5421         if (cls.state == ca_dedicated)
5422                 return NULL;
5423
5424         // if already loaded just return it, otherwise make a new skinframe
5425         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5426         if (skinframe && skinframe->base)
5427                 return skinframe;
5428
5429         skinframe->stain = NULL;
5430         skinframe->merged = NULL;
5431         skinframe->base = NULL;
5432         skinframe->pants = NULL;
5433         skinframe->shirt = NULL;
5434         skinframe->nmap = NULL;
5435         skinframe->gloss = NULL;
5436         skinframe->glow = NULL;
5437         skinframe->fog = NULL;
5438         skinframe->hasalpha = false;
5439
5440         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5441         if (!skindata)
5442                 return NULL;
5443
5444         if (developer_loading.integer)
5445                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5446
5447         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5448         if (textureflags & TEXF_ALPHA)
5449         {
5450                 for (i = 0;i < width * height;i++)
5451                 {
5452                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5453                         {
5454                                 skinframe->hasalpha = true;
5455                                 break;
5456                         }
5457                 }
5458                 if (r_loadfog && skinframe->hasalpha)
5459                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5460         }
5461
5462         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5463         //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]);
5464
5465         return skinframe;
5466 }
5467
5468 skinframe_t *R_SkinFrame_LoadMissing(void)
5469 {
5470         skinframe_t *skinframe;
5471
5472         if (cls.state == ca_dedicated)
5473                 return NULL;
5474
5475         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5476         skinframe->stain = NULL;
5477         skinframe->merged = NULL;
5478         skinframe->base = NULL;
5479         skinframe->pants = NULL;
5480         skinframe->shirt = NULL;
5481         skinframe->nmap = NULL;
5482         skinframe->gloss = NULL;
5483         skinframe->glow = NULL;
5484         skinframe->fog = NULL;
5485         skinframe->hasalpha = false;
5486
5487         skinframe->avgcolor[0] = rand() / RAND_MAX;
5488         skinframe->avgcolor[1] = rand() / RAND_MAX;
5489         skinframe->avgcolor[2] = rand() / RAND_MAX;
5490         skinframe->avgcolor[3] = 1;
5491
5492         return skinframe;
5493 }
5494
5495 void R_Main_FreeViewCache(void)
5496 {
5497         if (r_refdef.viewcache.entityvisible)
5498                 Mem_Free(r_refdef.viewcache.entityvisible);
5499         if (r_refdef.viewcache.world_pvsbits)
5500                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5501         if (r_refdef.viewcache.world_leafvisible)
5502                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5503         if (r_refdef.viewcache.world_surfacevisible)
5504                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5505         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5506 }
5507
5508 void R_Main_ResizeViewCache(void)
5509 {
5510         int numentities = r_refdef.scene.numentities;
5511         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5512         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5513         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5514         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5515         if (r_refdef.viewcache.maxentities < numentities)
5516         {
5517                 r_refdef.viewcache.maxentities = numentities;
5518                 if (r_refdef.viewcache.entityvisible)
5519                         Mem_Free(r_refdef.viewcache.entityvisible);
5520                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5521         }
5522         if (r_refdef.viewcache.world_numclusters != numclusters)
5523         {
5524                 r_refdef.viewcache.world_numclusters = numclusters;
5525                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5526                 if (r_refdef.viewcache.world_pvsbits)
5527                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5528                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5529         }
5530         if (r_refdef.viewcache.world_numleafs != numleafs)
5531         {
5532                 r_refdef.viewcache.world_numleafs = numleafs;
5533                 if (r_refdef.viewcache.world_leafvisible)
5534                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5535                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5536         }
5537         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5538         {
5539                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5540                 if (r_refdef.viewcache.world_surfacevisible)
5541                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5542                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5543         }
5544 }
5545
5546 extern rtexture_t *loadingscreentexture;
5547 void gl_main_start(void)
5548 {
5549         loadingscreentexture = NULL;
5550         r_texture_blanknormalmap = NULL;
5551         r_texture_white = NULL;
5552         r_texture_grey128 = NULL;
5553         r_texture_black = NULL;
5554         r_texture_whitecube = NULL;
5555         r_texture_normalizationcube = NULL;
5556         r_texture_fogattenuation = NULL;
5557         r_texture_gammaramps = NULL;
5558
5559         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5560         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5561
5562         switch(vid.renderpath)
5563         {
5564         case RENDERPATH_GL20:
5565         case RENDERPATH_CGGL:
5566                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5567                 Cvar_SetValueQuick(&gl_combine, 1);
5568                 Cvar_SetValueQuick(&r_glsl, 1);
5569                 r_loadnormalmap = true;
5570                 r_loadgloss = true;
5571                 r_loadfog = false;
5572                 break;
5573         case RENDERPATH_GL13:
5574                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5575                 Cvar_SetValueQuick(&gl_combine, 1);
5576                 Cvar_SetValueQuick(&r_glsl, 0);
5577                 r_loadnormalmap = false;
5578                 r_loadgloss = false;
5579                 r_loadfog = true;
5580                 break;
5581         case RENDERPATH_GL11:
5582                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5583                 Cvar_SetValueQuick(&gl_combine, 0);
5584                 Cvar_SetValueQuick(&r_glsl, 0);
5585                 r_loadnormalmap = false;
5586                 r_loadgloss = false;
5587                 r_loadfog = true;
5588                 break;
5589         }
5590
5591         R_AnimCache_Free();
5592         R_FrameData_Reset();
5593
5594         r_numqueries = 0;
5595         r_maxqueries = 0;
5596         memset(r_queries, 0, sizeof(r_queries));
5597
5598         r_qwskincache = NULL;
5599         r_qwskincache_size = 0;
5600
5601         // set up r_skinframe loading system for textures
5602         memset(&r_skinframe, 0, sizeof(r_skinframe));
5603         r_skinframe.loadsequence = 1;
5604         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5605
5606         r_main_texturepool = R_AllocTexturePool();
5607         R_BuildBlankTextures();
5608         R_BuildNoTexture();
5609         if (vid.support.arb_texture_cube_map)
5610         {
5611                 R_BuildWhiteCube();
5612                 R_BuildNormalizationCube();
5613         }
5614         r_texture_fogattenuation = NULL;
5615         r_texture_gammaramps = NULL;
5616         //r_texture_fogintensity = NULL;
5617         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5618         memset(&r_waterstate, 0, sizeof(r_waterstate));
5619         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5620         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5621 #ifdef SUPPORTCG
5622         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5623         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5624 #endif
5625         memset(&r_svbsp, 0, sizeof (r_svbsp));
5626
5627         r_refdef.fogmasktable_density = 0;
5628 }
5629
5630 void gl_main_shutdown(void)
5631 {
5632         R_AnimCache_Free();
5633         R_FrameData_Reset();
5634
5635         R_Main_FreeViewCache();
5636
5637         if (r_maxqueries)
5638                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5639
5640         r_numqueries = 0;
5641         r_maxqueries = 0;
5642         memset(r_queries, 0, sizeof(r_queries));
5643
5644         r_qwskincache = NULL;
5645         r_qwskincache_size = 0;
5646
5647         // clear out the r_skinframe state
5648         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5649         memset(&r_skinframe, 0, sizeof(r_skinframe));
5650
5651         if (r_svbsp.nodes)
5652                 Mem_Free(r_svbsp.nodes);
5653         memset(&r_svbsp, 0, sizeof (r_svbsp));
5654         R_FreeTexturePool(&r_main_texturepool);
5655         loadingscreentexture = NULL;
5656         r_texture_blanknormalmap = NULL;
5657         r_texture_white = NULL;
5658         r_texture_grey128 = NULL;
5659         r_texture_black = NULL;
5660         r_texture_whitecube = NULL;
5661         r_texture_normalizationcube = NULL;
5662         r_texture_fogattenuation = NULL;
5663         r_texture_gammaramps = NULL;
5664         //r_texture_fogintensity = NULL;
5665         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5666         memset(&r_waterstate, 0, sizeof(r_waterstate));
5667         R_GLSL_Restart_f();
5668 }
5669
5670 extern void CL_ParseEntityLump(char *entitystring);
5671 void gl_main_newmap(void)
5672 {
5673         // FIXME: move this code to client
5674         int l;
5675         char *entities, entname[MAX_QPATH];
5676         if (r_qwskincache)
5677                 Mem_Free(r_qwskincache);
5678         r_qwskincache = NULL;
5679         r_qwskincache_size = 0;
5680         if (cl.worldmodel)
5681         {
5682                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5683                 l = (int)strlen(entname) - 4;
5684                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5685                 {
5686                         memcpy(entname + l, ".ent", 5);
5687                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5688                         {
5689                                 CL_ParseEntityLump(entities);
5690                                 Mem_Free(entities);
5691                                 return;
5692                         }
5693                 }
5694                 if (cl.worldmodel->brush.entities)
5695                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5696         }
5697         R_Main_FreeViewCache();
5698
5699         R_FrameData_Reset();
5700 }
5701
5702 void GL_Main_Init(void)
5703 {
5704         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5705
5706         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5707         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5708         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5709         if (gamemode == GAME_NEHAHRA)
5710         {
5711                 Cvar_RegisterVariable (&gl_fogenable);
5712                 Cvar_RegisterVariable (&gl_fogdensity);
5713                 Cvar_RegisterVariable (&gl_fogred);
5714                 Cvar_RegisterVariable (&gl_foggreen);
5715                 Cvar_RegisterVariable (&gl_fogblue);
5716                 Cvar_RegisterVariable (&gl_fogstart);
5717                 Cvar_RegisterVariable (&gl_fogend);
5718                 Cvar_RegisterVariable (&gl_skyclip);
5719         }
5720         Cvar_RegisterVariable(&r_motionblur);
5721         Cvar_RegisterVariable(&r_motionblur_maxblur);
5722         Cvar_RegisterVariable(&r_motionblur_bmin);
5723         Cvar_RegisterVariable(&r_motionblur_vmin);
5724         Cvar_RegisterVariable(&r_motionblur_vmax);
5725         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5726         Cvar_RegisterVariable(&r_motionblur_randomize);
5727         Cvar_RegisterVariable(&r_damageblur);
5728         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5729         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5730         Cvar_RegisterVariable(&r_equalize_entities_by);
5731         Cvar_RegisterVariable(&r_equalize_entities_to);
5732         Cvar_RegisterVariable(&r_depthfirst);
5733         Cvar_RegisterVariable(&r_useinfinitefarclip);
5734         Cvar_RegisterVariable(&r_farclip_base);
5735         Cvar_RegisterVariable(&r_farclip_world);
5736         Cvar_RegisterVariable(&r_nearclip);
5737         Cvar_RegisterVariable(&r_showbboxes);
5738         Cvar_RegisterVariable(&r_showsurfaces);
5739         Cvar_RegisterVariable(&r_showtris);
5740         Cvar_RegisterVariable(&r_shownormals);
5741         Cvar_RegisterVariable(&r_showlighting);
5742         Cvar_RegisterVariable(&r_showshadowvolumes);
5743         Cvar_RegisterVariable(&r_showcollisionbrushes);
5744         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5745         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5746         Cvar_RegisterVariable(&r_showdisabledepthtest);
5747         Cvar_RegisterVariable(&r_drawportals);
5748         Cvar_RegisterVariable(&r_drawentities);
5749         Cvar_RegisterVariable(&r_cullentities_trace);
5750         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5751         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5752         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5753         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5754         Cvar_RegisterVariable(&r_drawviewmodel);
5755         Cvar_RegisterVariable(&r_speeds);
5756         Cvar_RegisterVariable(&r_fullbrights);
5757         Cvar_RegisterVariable(&r_wateralpha);
5758         Cvar_RegisterVariable(&r_dynamic);
5759         Cvar_RegisterVariable(&r_fullbright);
5760         Cvar_RegisterVariable(&r_shadows);
5761         Cvar_RegisterVariable(&r_shadows_darken);
5762         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5763         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5764         Cvar_RegisterVariable(&r_shadows_throwdistance);
5765         Cvar_RegisterVariable(&r_shadows_throwdirection);
5766         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5767         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5768         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5769         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5770         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5771         Cvar_RegisterVariable(&r_fog_exp2);
5772         Cvar_RegisterVariable(&r_drawfog);
5773         Cvar_RegisterVariable(&r_transparentdepthmasking);
5774         Cvar_RegisterVariable(&r_texture_dds_load);
5775         Cvar_RegisterVariable(&r_texture_dds_save);
5776         Cvar_RegisterVariable(&r_textureunits);
5777         Cvar_RegisterVariable(&gl_combine);
5778         Cvar_RegisterVariable(&r_glsl);
5779         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5780         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5781         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5782         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5783         Cvar_RegisterVariable(&r_glsl_postprocess);
5784         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5785         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5786         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5787         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5788         Cvar_RegisterVariable(&r_water);
5789         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5790         Cvar_RegisterVariable(&r_water_clippingplanebias);
5791         Cvar_RegisterVariable(&r_water_refractdistort);
5792         Cvar_RegisterVariable(&r_water_reflectdistort);
5793         Cvar_RegisterVariable(&r_lerpsprites);
5794         Cvar_RegisterVariable(&r_lerpmodels);
5795         Cvar_RegisterVariable(&r_lerplightstyles);
5796         Cvar_RegisterVariable(&r_waterscroll);
5797         Cvar_RegisterVariable(&r_bloom);
5798         Cvar_RegisterVariable(&r_bloom_colorscale);
5799         Cvar_RegisterVariable(&r_bloom_brighten);
5800         Cvar_RegisterVariable(&r_bloom_blur);
5801         Cvar_RegisterVariable(&r_bloom_resolution);
5802         Cvar_RegisterVariable(&r_bloom_colorexponent);
5803         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5804         Cvar_RegisterVariable(&r_hdr);
5805         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5806         Cvar_RegisterVariable(&r_hdr_glowintensity);
5807         Cvar_RegisterVariable(&r_hdr_range);
5808         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5809         Cvar_RegisterVariable(&developer_texturelogging);
5810         Cvar_RegisterVariable(&gl_lightmaps);
5811         Cvar_RegisterVariable(&r_test);
5812         Cvar_RegisterVariable(&r_batchmode);
5813         Cvar_RegisterVariable(&r_glsl_saturation);
5814         Cvar_RegisterVariable(&r_framedatasize);
5815         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5816                 Cvar_SetValue("r_fullbrights", 0);
5817         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5818
5819         Cvar_RegisterVariable(&r_track_sprites);
5820         Cvar_RegisterVariable(&r_track_sprites_flags);
5821         Cvar_RegisterVariable(&r_track_sprites_scalew);
5822         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5823         Cvar_RegisterVariable(&r_overheadsprites_perspective);
5824         Cvar_RegisterVariable(&r_overheadsprites_pushback);
5825 }
5826
5827 extern void R_Textures_Init(void);
5828 extern void GL_Draw_Init(void);
5829 extern void GL_Main_Init(void);
5830 extern void R_Shadow_Init(void);
5831 extern void R_Sky_Init(void);
5832 extern void GL_Surf_Init(void);
5833 extern void R_Particles_Init(void);
5834 extern void R_Explosion_Init(void);
5835 extern void gl_backend_init(void);
5836 extern void Sbar_Init(void);
5837 extern void R_LightningBeams_Init(void);
5838 extern void Mod_RenderInit(void);
5839 extern void Font_Init(void);
5840
5841 void Render_Init(void)
5842 {
5843         gl_backend_init();
5844         R_Textures_Init();
5845         GL_Main_Init();
5846         Font_Init();
5847         GL_Draw_Init();
5848         R_Shadow_Init();
5849         R_Sky_Init();
5850         GL_Surf_Init();
5851         Sbar_Init();
5852         R_Particles_Init();
5853         R_Explosion_Init();
5854         R_LightningBeams_Init();
5855         Mod_RenderInit();
5856 }
5857
5858 /*
5859 ===============
5860 GL_Init
5861 ===============
5862 */
5863 extern char *ENGINE_EXTENSIONS;
5864 void GL_Init (void)
5865 {
5866         gl_renderer = (const char *)qglGetString(GL_RENDERER);
5867         gl_vendor = (const char *)qglGetString(GL_VENDOR);
5868         gl_version = (const char *)qglGetString(GL_VERSION);
5869         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5870
5871         if (!gl_extensions)
5872                 gl_extensions = "";
5873         if (!gl_platformextensions)
5874                 gl_platformextensions = "";
5875
5876         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5877         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5878         Con_Printf("GL_VERSION: %s\n", gl_version);
5879         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
5880         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
5881
5882         VID_CheckExtensions();
5883
5884         // LordHavoc: report supported extensions
5885         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
5886
5887         // clear to black (loading plaque will be seen over this)
5888         CHECKGLERROR
5889         qglClearColor(0,0,0,1);CHECKGLERROR
5890         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
5891 }
5892
5893 int R_CullBox(const vec3_t mins, const vec3_t maxs)
5894 {
5895         int i;
5896         mplane_t *p;
5897         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5898         {
5899                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
5900                 if (i == 4)
5901                         continue;
5902                 p = r_refdef.view.frustum + i;
5903                 switch(p->signbits)
5904                 {
5905                 default:
5906                 case 0:
5907                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5908                                 return true;
5909                         break;
5910                 case 1:
5911                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5912                                 return true;
5913                         break;
5914                 case 2:
5915                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5916                                 return true;
5917                         break;
5918                 case 3:
5919                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5920                                 return true;
5921                         break;
5922                 case 4:
5923                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5924                                 return true;
5925                         break;
5926                 case 5:
5927                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5928                                 return true;
5929                         break;
5930                 case 6:
5931                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5932                                 return true;
5933                         break;
5934                 case 7:
5935                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5936                                 return true;
5937                         break;
5938                 }
5939         }
5940         return false;
5941 }
5942
5943 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
5944 {
5945         int i;
5946         const mplane_t *p;
5947         for (i = 0;i < numplanes;i++)
5948         {
5949                 p = planes + i;
5950                 switch(p->signbits)
5951                 {
5952                 default:
5953                 case 0:
5954                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5955                                 return true;
5956                         break;
5957                 case 1:
5958                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5959                                 return true;
5960                         break;
5961                 case 2:
5962                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5963                                 return true;
5964                         break;
5965                 case 3:
5966                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5967                                 return true;
5968                         break;
5969                 case 4:
5970                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5971                                 return true;
5972                         break;
5973                 case 5:
5974                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5975                                 return true;
5976                         break;
5977                 case 6:
5978                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5979                                 return true;
5980                         break;
5981                 case 7:
5982                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5983                                 return true;
5984                         break;
5985                 }
5986         }
5987         return false;
5988 }
5989
5990 //==================================================================================
5991
5992 // LordHavoc: this stores temporary data used within the same frame
5993
5994 qboolean r_framedata_failed;
5995 static size_t r_framedata_size;
5996 static size_t r_framedata_current;
5997 static void *r_framedata_base;
5998
5999 void R_FrameData_Reset(void)
6000 {
6001         if (r_framedata_base)
6002                 Mem_Free(r_framedata_base);
6003         r_framedata_base = NULL;
6004         r_framedata_size = 0;
6005         r_framedata_current = 0;
6006         r_framedata_failed = false;
6007 }
6008
6009 void R_FrameData_NewFrame(void)
6010 {
6011         size_t wantedsize;
6012         if (r_framedata_failed)
6013                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6014         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6015         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6016         if (r_framedata_size != wantedsize)
6017         {
6018                 r_framedata_size = wantedsize;
6019                 if (r_framedata_base)
6020                         Mem_Free(r_framedata_base);
6021                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6022         }
6023         r_framedata_current = 0;
6024         r_framedata_failed = false;
6025 }
6026
6027 void *R_FrameData_Alloc(size_t size)
6028 {
6029         void *data;
6030
6031         // align to 16 byte boundary
6032         size = (size + 15) & ~15;
6033         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6034         r_framedata_current += size;
6035
6036         // check overflow
6037         if (r_framedata_current > r_framedata_size)
6038                 r_framedata_failed = true;
6039
6040         // return NULL on everything after a failure
6041         if (r_framedata_failed)
6042                 return NULL;
6043
6044         return data;
6045 }
6046
6047 void *R_FrameData_Store(size_t size, void *data)
6048 {
6049         void *d = R_FrameData_Alloc(size);
6050         if (d)
6051                 memcpy(d, data, size);
6052         return d;
6053 }
6054
6055 //==================================================================================
6056
6057 // LordHavoc: animcache originally written by Echon, rewritten since then
6058
6059 /**
6060  * Animation cache prevents re-generating mesh data for an animated model
6061  * multiple times in one frame for lighting, shadowing, reflections, etc.
6062  */
6063
6064 void R_AnimCache_Free(void)
6065 {
6066 }
6067
6068 void R_AnimCache_ClearCache(void)
6069 {
6070         int i;
6071         entity_render_t *ent;
6072
6073         for (i = 0;i < r_refdef.scene.numentities;i++)
6074         {
6075                 ent = r_refdef.scene.entities[i];
6076                 ent->animcache_vertex3f = NULL;
6077                 ent->animcache_normal3f = NULL;
6078                 ent->animcache_svector3f = NULL;
6079                 ent->animcache_tvector3f = NULL;
6080         }
6081 }
6082
6083 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6084 {
6085         dp_model_t *model = ent->model;
6086         int numvertices;
6087         // see if it's already cached this frame
6088         if (ent->animcache_vertex3f)
6089         {
6090                 // add normals/tangents if needed
6091                 if (wantnormals || wanttangents)
6092                 {
6093                         if (ent->animcache_normal3f)
6094                                 wantnormals = false;
6095                         if (ent->animcache_svector3f)
6096                                 wanttangents = false;
6097                         if (wantnormals || wanttangents)
6098                         {
6099                                 numvertices = model->surfmesh.num_vertices;
6100                                 if (wantnormals)
6101                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6102                                 if (wanttangents)
6103                                 {
6104                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6105                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6106                                 }
6107                                 if (!r_framedata_failed)
6108                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6109                         }
6110                 }
6111         }
6112         else
6113         {
6114                 // see if this ent is worth caching
6115                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6116                         return false;
6117                 // get some memory for this entity and generate mesh data
6118                 numvertices = model->surfmesh.num_vertices;
6119                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6120                 if (wantnormals)
6121                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6122                 if (wanttangents)
6123                 {
6124                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6125                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6126                 }
6127                 if (!r_framedata_failed)
6128                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6129         }
6130         return !r_framedata_failed;
6131 }
6132
6133 void R_AnimCache_CacheVisibleEntities(void)
6134 {
6135         int i;
6136         qboolean wantnormals = !r_showsurfaces.integer;
6137         qboolean wanttangents = !r_showsurfaces.integer;
6138
6139         switch(vid.renderpath)
6140         {
6141         case RENDERPATH_GL20:
6142         case RENDERPATH_CGGL:
6143                 break;
6144         case RENDERPATH_GL13:
6145         case RENDERPATH_GL11:
6146                 wanttangents = false;
6147                 break;
6148         }
6149
6150         // TODO: thread this
6151         // NOTE: R_PrepareRTLights() also caches entities
6152
6153         for (i = 0;i < r_refdef.scene.numentities;i++)
6154                 if (r_refdef.viewcache.entityvisible[i])
6155                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6156
6157         if (r_shadows.integer)
6158                 for (i = 0;i < r_refdef.scene.numentities;i++)
6159                         if (!r_refdef.viewcache.entityvisible[i])
6160                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6161 }
6162
6163 //==================================================================================
6164
6165 static void R_View_UpdateEntityLighting (void)
6166 {
6167         int i;
6168         entity_render_t *ent;
6169         vec3_t tempdiffusenormal, avg;
6170         vec_t f, fa, fd, fdd;
6171
6172         for (i = 0;i < r_refdef.scene.numentities;i++)
6173         {
6174                 ent = r_refdef.scene.entities[i];
6175
6176                 // skip unseen models
6177                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6178                         continue;
6179
6180                 // skip bsp models
6181                 if (ent->model && ent->model->brush.num_leafs)
6182                 {
6183                         // TODO: use modellight for r_ambient settings on world?
6184                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6185                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6186                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6187                         continue;
6188                 }
6189
6190                 // fetch the lighting from the worldmodel data
6191                 VectorClear(ent->modellight_ambient);
6192                 VectorClear(ent->modellight_diffuse);
6193                 VectorClear(tempdiffusenormal);
6194                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6195                 {
6196                         vec3_t org;
6197                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6198                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6199                         if(ent->flags & RENDER_EQUALIZE)
6200                         {
6201                                 // first fix up ambient lighting...
6202                                 if(r_equalize_entities_minambient.value > 0)
6203                                 {
6204                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6205                                         if(fd > 0)
6206                                         {
6207                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6208                                                 if(fa < r_equalize_entities_minambient.value * fd)
6209                                                 {
6210                                                         // solve:
6211                                                         //   fa'/fd' = minambient
6212                                                         //   fa'+0.25*fd' = fa+0.25*fd
6213                                                         //   ...
6214                                                         //   fa' = fd' * minambient
6215                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6216                                                         //   ...
6217                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6218                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6219                                                         //   ...
6220                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6221                                                         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
6222                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6223                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6224                                                 }
6225                                         }
6226                                 }
6227
6228                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6229                                 {
6230                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6231                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6232                                         if(f > 0)
6233                                         {
6234                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6235                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6236                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6237                                         }
6238                                 }
6239                         }
6240                 }
6241                 else // highly rare
6242                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6243
6244                 // move the light direction into modelspace coordinates for lighting code
6245                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6246                 if(VectorLength2(ent->modellight_lightdir) == 0)
6247                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6248                 VectorNormalize(ent->modellight_lightdir);
6249         }
6250 }
6251
6252 #define MAX_LINEOFSIGHTTRACES 64
6253
6254 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6255 {
6256         int i;
6257         vec3_t boxmins, boxmaxs;
6258         vec3_t start;
6259         vec3_t end;
6260         dp_model_t *model = r_refdef.scene.worldmodel;
6261
6262         if (!model || !model->brush.TraceLineOfSight)
6263                 return true;
6264
6265         // expand the box a little
6266         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6267         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6268         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6269         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6270         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6271         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6272
6273         // try center
6274         VectorCopy(eye, start);
6275         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6276         if (model->brush.TraceLineOfSight(model, start, end))
6277                 return true;
6278
6279         // try various random positions
6280         for (i = 0;i < numsamples;i++)
6281         {
6282                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6283                 if (model->brush.TraceLineOfSight(model, start, end))
6284                         return true;
6285         }
6286
6287         return false;
6288 }
6289
6290
6291 static void R_View_UpdateEntityVisible (void)
6292 {
6293         int i;
6294         int renderimask;
6295         int samples;
6296         entity_render_t *ent;
6297
6298         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6299         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6300         {
6301                 // worldmodel can check visibility
6302                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6303                 for (i = 0;i < r_refdef.scene.numentities;i++)
6304                 {
6305                         ent = r_refdef.scene.entities[i];
6306                         if (!(ent->flags & renderimask))
6307                         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)))
6308                         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))
6309                                 r_refdef.viewcache.entityvisible[i] = true;
6310                 }
6311                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6312                 {
6313                         for (i = 0;i < r_refdef.scene.numentities;i++)
6314                         {
6315                                 ent = r_refdef.scene.entities[i];
6316                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6317                                 {
6318                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6319                                         if (samples < 0)
6320                                                 continue; // temp entities do pvs only
6321                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6322                                                 ent->last_trace_visibility = realtime;
6323                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6324                                                 r_refdef.viewcache.entityvisible[i] = 0;
6325                                 }
6326                         }
6327                 }
6328         }
6329         else
6330         {
6331                 // no worldmodel or it can't check visibility
6332                 for (i = 0;i < r_refdef.scene.numentities;i++)
6333                 {
6334                         ent = r_refdef.scene.entities[i];
6335                         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));
6336                 }
6337         }
6338 }
6339
6340 /// only used if skyrendermasked, and normally returns false
6341 int R_DrawBrushModelsSky (void)
6342 {
6343         int i, sky;
6344         entity_render_t *ent;
6345
6346         sky = false;
6347         for (i = 0;i < r_refdef.scene.numentities;i++)
6348         {
6349                 if (!r_refdef.viewcache.entityvisible[i])
6350                         continue;
6351                 ent = r_refdef.scene.entities[i];
6352                 if (!ent->model || !ent->model->DrawSky)
6353                         continue;
6354                 ent->model->DrawSky(ent);
6355                 sky = true;
6356         }
6357         return sky;
6358 }
6359
6360 static void R_DrawNoModel(entity_render_t *ent);
6361 static void R_DrawModels(void)
6362 {
6363         int i;
6364         entity_render_t *ent;
6365
6366         for (i = 0;i < r_refdef.scene.numentities;i++)
6367         {
6368                 if (!r_refdef.viewcache.entityvisible[i])
6369                         continue;
6370                 ent = r_refdef.scene.entities[i];
6371                 r_refdef.stats.entities++;
6372                 if (ent->model && ent->model->Draw != NULL)
6373                         ent->model->Draw(ent);
6374                 else
6375                         R_DrawNoModel(ent);
6376         }
6377 }
6378
6379 static void R_DrawModelsDepth(void)
6380 {
6381         int i;
6382         entity_render_t *ent;
6383
6384         for (i = 0;i < r_refdef.scene.numentities;i++)
6385         {
6386                 if (!r_refdef.viewcache.entityvisible[i])
6387                         continue;
6388                 ent = r_refdef.scene.entities[i];
6389                 if (ent->model && ent->model->DrawDepth != NULL)
6390                         ent->model->DrawDepth(ent);
6391         }
6392 }
6393
6394 static void R_DrawModelsDebug(void)
6395 {
6396         int i;
6397         entity_render_t *ent;
6398
6399         for (i = 0;i < r_refdef.scene.numentities;i++)
6400         {
6401                 if (!r_refdef.viewcache.entityvisible[i])
6402                         continue;
6403                 ent = r_refdef.scene.entities[i];
6404                 if (ent->model && ent->model->DrawDebug != NULL)
6405                         ent->model->DrawDebug(ent);
6406         }
6407 }
6408
6409 static void R_DrawModelsAddWaterPlanes(void)
6410 {
6411         int i;
6412         entity_render_t *ent;
6413
6414         for (i = 0;i < r_refdef.scene.numentities;i++)
6415         {
6416                 if (!r_refdef.viewcache.entityvisible[i])
6417                         continue;
6418                 ent = r_refdef.scene.entities[i];
6419                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6420                         ent->model->DrawAddWaterPlanes(ent);
6421         }
6422 }
6423
6424 static void R_View_SetFrustum(void)
6425 {
6426         int i;
6427         double slopex, slopey;
6428         vec3_t forward, left, up, origin;
6429
6430         // we can't trust r_refdef.view.forward and friends in reflected scenes
6431         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6432
6433 #if 0
6434         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6435         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6436         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6437         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6438         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6439         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6440         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6441         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6442         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6443         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6444         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6445         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6446 #endif
6447
6448 #if 0
6449         zNear = r_refdef.nearclip;
6450         nudge = 1.0 - 1.0 / (1<<23);
6451         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6452         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6453         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6454         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6455         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6456         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6457         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6458         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6459 #endif
6460
6461
6462
6463 #if 0
6464         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6465         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6466         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6467         r_refdef.view.frustum[0].dist = m[15] - m[12];
6468
6469         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6470         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6471         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6472         r_refdef.view.frustum[1].dist = m[15] + m[12];
6473
6474         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6475         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6476         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6477         r_refdef.view.frustum[2].dist = m[15] - m[13];
6478
6479         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6480         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6481         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6482         r_refdef.view.frustum[3].dist = m[15] + m[13];
6483
6484         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6485         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6486         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6487         r_refdef.view.frustum[4].dist = m[15] - m[14];
6488
6489         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6490         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6491         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6492         r_refdef.view.frustum[5].dist = m[15] + m[14];
6493 #endif
6494
6495         if (r_refdef.view.useperspective)
6496         {
6497                 slopex = 1.0 / r_refdef.view.frustum_x;
6498                 slopey = 1.0 / r_refdef.view.frustum_y;
6499                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6500                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6501                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6502                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6503                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6504
6505                 // Leaving those out was a mistake, those were in the old code, and they
6506                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6507                 // I couldn't reproduce it after adding those normalizations. --blub
6508                 VectorNormalize(r_refdef.view.frustum[0].normal);
6509                 VectorNormalize(r_refdef.view.frustum[1].normal);
6510                 VectorNormalize(r_refdef.view.frustum[2].normal);
6511                 VectorNormalize(r_refdef.view.frustum[3].normal);
6512
6513                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6514                 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]);
6515                 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]);
6516                 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]);
6517                 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]);
6518
6519                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6520                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6521                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6522                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6523                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6524         }
6525         else
6526         {
6527                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6528                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6529                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6530                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6531                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6532                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6533                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6534                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6535                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6536                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6537         }
6538         r_refdef.view.numfrustumplanes = 5;
6539
6540         if (r_refdef.view.useclipplane)
6541         {
6542                 r_refdef.view.numfrustumplanes = 6;
6543                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6544         }
6545
6546         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6547                 PlaneClassify(r_refdef.view.frustum + i);
6548
6549         // LordHavoc: note to all quake engine coders, Quake had a special case
6550         // for 90 degrees which assumed a square view (wrong), so I removed it,
6551         // Quake2 has it disabled as well.
6552
6553         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6554         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6555         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6556         //PlaneClassify(&frustum[0]);
6557
6558         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6559         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6560         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6561         //PlaneClassify(&frustum[1]);
6562
6563         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6564         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6565         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6566         //PlaneClassify(&frustum[2]);
6567
6568         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6569         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6570         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6571         //PlaneClassify(&frustum[3]);
6572
6573         // nearclip plane
6574         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6575         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6576         //PlaneClassify(&frustum[4]);
6577 }
6578
6579 void R_View_Update(void)
6580 {
6581         R_Main_ResizeViewCache();
6582         R_View_SetFrustum();
6583         R_View_WorldVisibility(r_refdef.view.useclipplane);
6584         R_View_UpdateEntityVisible();
6585         R_View_UpdateEntityLighting();
6586 }
6587
6588 void R_SetupView(qboolean allowwaterclippingplane)
6589 {
6590         const float *customclipplane = NULL;
6591         float plane[4];
6592         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6593         {
6594                 // LordHavoc: couldn't figure out how to make this approach the
6595                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6596                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6597                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6598                         dist = r_refdef.view.clipplane.dist;
6599                 plane[0] = r_refdef.view.clipplane.normal[0];
6600                 plane[1] = r_refdef.view.clipplane.normal[1];
6601                 plane[2] = r_refdef.view.clipplane.normal[2];
6602                 plane[3] = dist;
6603                 customclipplane = plane;
6604         }
6605
6606         if (!r_refdef.view.useperspective)
6607                 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);
6608         else if (vid.stencil && r_useinfinitefarclip.integer)
6609                 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);
6610         else
6611                 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);
6612         R_SetViewport(&r_refdef.view.viewport);
6613 }
6614
6615 void R_EntityMatrix(const matrix4x4_t *matrix)
6616 {
6617         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6618         {
6619                 gl_modelmatrixchanged = false;
6620                 gl_modelmatrix = *matrix;
6621                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6622                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6623                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6624                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6625                 CHECKGLERROR
6626                 switch(vid.renderpath)
6627                 {
6628                 case RENDERPATH_GL20:
6629                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6630                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6631                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6632                         break;
6633                 case RENDERPATH_CGGL:
6634 #ifdef SUPPORTCG
6635                         CHECKCGERROR
6636                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6637                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6638                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6639 #endif
6640                         break;
6641                 case RENDERPATH_GL13:
6642                 case RENDERPATH_GL11:
6643                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6644                         break;
6645                 }
6646         }
6647 }
6648
6649 void R_ResetViewRendering2D(void)
6650 {
6651         r_viewport_t viewport;
6652         DrawQ_Finish();
6653
6654         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6655         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);
6656         R_SetViewport(&viewport);
6657         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6658         GL_Color(1, 1, 1, 1);
6659         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6660         GL_BlendFunc(GL_ONE, GL_ZERO);
6661         GL_AlphaTest(false);
6662         GL_ScissorTest(false);
6663         GL_DepthMask(false);
6664         GL_DepthRange(0, 1);
6665         GL_DepthTest(false);
6666         R_EntityMatrix(&identitymatrix);
6667         R_Mesh_ResetTextureState();
6668         GL_PolygonOffset(0, 0);
6669         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6670         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6671         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6672         qglStencilMask(~0);CHECKGLERROR
6673         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6674         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6675         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6676 }
6677
6678 void R_ResetViewRendering3D(void)
6679 {
6680         DrawQ_Finish();
6681
6682         R_SetupView(true);
6683         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6684         GL_Color(1, 1, 1, 1);
6685         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6686         GL_BlendFunc(GL_ONE, GL_ZERO);
6687         GL_AlphaTest(false);
6688         GL_ScissorTest(true);
6689         GL_DepthMask(true);
6690         GL_DepthRange(0, 1);
6691         GL_DepthTest(true);
6692         R_EntityMatrix(&identitymatrix);
6693         R_Mesh_ResetTextureState();
6694         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6695         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6696         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6697         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6698         qglStencilMask(~0);CHECKGLERROR
6699         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6700         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6701         GL_CullFace(r_refdef.view.cullface_back);
6702 }
6703
6704 void R_RenderScene(void);
6705 void R_RenderWaterPlanes(void);
6706
6707 static void R_Water_StartFrame(void)
6708 {
6709         int i;
6710         int waterwidth, waterheight, texturewidth, textureheight;
6711         r_waterstate_waterplane_t *p;
6712
6713         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6714                 return;
6715
6716         switch(vid.renderpath)
6717         {
6718         case RENDERPATH_GL20:
6719         case RENDERPATH_CGGL:
6720                 break;
6721         case RENDERPATH_GL13:
6722         case RENDERPATH_GL11:
6723                 return;
6724         }
6725
6726         // set waterwidth and waterheight to the water resolution that will be
6727         // used (often less than the screen resolution for faster rendering)
6728         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6729         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6730
6731         // calculate desired texture sizes
6732         // can't use water if the card does not support the texture size
6733         if (!r_water.integer || r_showsurfaces.integer)
6734                 texturewidth = textureheight = waterwidth = waterheight = 0;
6735         else if (vid.support.arb_texture_non_power_of_two)
6736         {
6737                 texturewidth = waterwidth;
6738                 textureheight = waterheight;
6739         }
6740         else
6741         {
6742                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6743                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6744         }
6745
6746         // allocate textures as needed
6747         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6748         {
6749                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6750                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6751                 {
6752                         if (p->texture_refraction)
6753                                 R_FreeTexture(p->texture_refraction);
6754                         p->texture_refraction = NULL;
6755                         if (p->texture_reflection)
6756                                 R_FreeTexture(p->texture_reflection);
6757                         p->texture_reflection = NULL;
6758                 }
6759                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6760                 r_waterstate.texturewidth = texturewidth;
6761                 r_waterstate.textureheight = textureheight;
6762         }
6763
6764         if (r_waterstate.texturewidth)
6765         {
6766                 r_waterstate.enabled = true;
6767
6768                 // when doing a reduced render (HDR) we want to use a smaller area
6769                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6770                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6771
6772                 // set up variables that will be used in shader setup
6773                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6774                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6775                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6776                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6777         }
6778
6779         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6780         r_waterstate.numwaterplanes = 0;
6781 }
6782
6783 void R_Water_AddWaterPlane(msurface_t *surface)
6784 {
6785         int triangleindex, planeindex;
6786         const int *e;
6787         vec3_t vert[3];
6788         vec3_t normal;
6789         vec3_t center;
6790         mplane_t plane;
6791         r_waterstate_waterplane_t *p;
6792         texture_t *t = R_GetCurrentTexture(surface->texture);
6793         // just use the first triangle with a valid normal for any decisions
6794         VectorClear(normal);
6795         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6796         {
6797                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6798                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6799                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6800                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6801                 if (VectorLength2(normal) >= 0.001)
6802                         break;
6803         }
6804
6805         VectorCopy(normal, plane.normal);
6806         VectorNormalize(plane.normal);
6807         plane.dist = DotProduct(vert[0], plane.normal);
6808         PlaneClassify(&plane);
6809         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6810         {
6811                 // skip backfaces (except if nocullface is set)
6812                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6813                         return;
6814                 VectorNegate(plane.normal, plane.normal);
6815                 plane.dist *= -1;
6816                 PlaneClassify(&plane);
6817         }
6818
6819
6820         // find a matching plane if there is one
6821         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6822                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6823                         break;
6824         if (planeindex >= r_waterstate.maxwaterplanes)
6825                 return; // nothing we can do, out of planes
6826
6827         // if this triangle does not fit any known plane rendered this frame, add one
6828         if (planeindex >= r_waterstate.numwaterplanes)
6829         {
6830                 // store the new plane
6831                 r_waterstate.numwaterplanes++;
6832                 p->plane = plane;
6833                 // clear materialflags and pvs
6834                 p->materialflags = 0;
6835                 p->pvsvalid = false;
6836         }
6837         // merge this surface's materialflags into the waterplane
6838         p->materialflags |= t->currentmaterialflags;
6839         // merge this surface's PVS into the waterplane
6840         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6841         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6842          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6843         {
6844                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6845                 p->pvsvalid = true;
6846         }
6847 }
6848
6849 static void R_Water_ProcessPlanes(void)
6850 {
6851         r_refdef_view_t originalview;
6852         r_refdef_view_t myview;
6853         int planeindex;
6854         r_waterstate_waterplane_t *p;
6855
6856         originalview = r_refdef.view;
6857
6858         // make sure enough textures are allocated
6859         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6860         {
6861                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6862                 {
6863                         if (!p->texture_refraction)
6864                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6865                         if (!p->texture_refraction)
6866                                 goto error;
6867                 }
6868
6869                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6870                 {
6871                         if (!p->texture_reflection)
6872                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6873                         if (!p->texture_reflection)
6874                                 goto error;
6875                 }
6876         }
6877
6878         // render views
6879         r_refdef.view = originalview;
6880         r_refdef.view.showdebug = false;
6881         r_refdef.view.width = r_waterstate.waterwidth;
6882         r_refdef.view.height = r_waterstate.waterheight;
6883         r_refdef.view.useclipplane = true;
6884         myview = r_refdef.view;
6885         r_waterstate.renderingscene = true;
6886         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6887         {
6888                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6889                 {
6890                         r_refdef.view = myview;
6891                         // render reflected scene and copy into texture
6892                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6893                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6894                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6895                         r_refdef.view.clipplane = p->plane;
6896                         // reverse the cullface settings for this render
6897                         r_refdef.view.cullface_front = GL_FRONT;
6898                         r_refdef.view.cullface_back = GL_BACK;
6899                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6900                         {
6901                                 r_refdef.view.usecustompvs = true;
6902                                 if (p->pvsvalid)
6903                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6904                                 else
6905                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6906                         }
6907
6908                         R_ResetViewRendering3D();
6909                         R_ClearScreen(r_refdef.fogenabled);
6910                         R_View_Update();
6911                         R_RenderScene();
6912
6913                         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);
6914                 }
6915
6916                 // render the normal view scene and copy into texture
6917                 // (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)
6918                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6919                 {
6920                         r_refdef.view = myview;
6921                         r_refdef.view.clipplane = p->plane;
6922                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6923                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6924                         PlaneClassify(&r_refdef.view.clipplane);
6925
6926                         R_ResetViewRendering3D();
6927                         R_ClearScreen(r_refdef.fogenabled);
6928                         R_View_Update();
6929                         R_RenderScene();
6930
6931                         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);
6932                 }
6933
6934         }
6935         r_waterstate.renderingscene = false;
6936         r_refdef.view = originalview;
6937         R_ResetViewRendering3D();
6938         R_ClearScreen(r_refdef.fogenabled);
6939         R_View_Update();
6940         return;
6941 error:
6942         r_refdef.view = originalview;
6943         r_waterstate.renderingscene = false;
6944         Cvar_SetValueQuick(&r_water, 0);
6945         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6946         return;
6947 }
6948
6949 void R_Bloom_StartFrame(void)
6950 {
6951         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6952
6953         switch(vid.renderpath)
6954         {
6955         case RENDERPATH_GL20:
6956         case RENDERPATH_CGGL:
6957                 break;
6958         case RENDERPATH_GL13:
6959         case RENDERPATH_GL11:
6960                 return;
6961         }
6962
6963         // set bloomwidth and bloomheight to the bloom resolution that will be
6964         // used (often less than the screen resolution for faster rendering)
6965         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6966         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6967         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6968         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6969         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6970
6971         // calculate desired texture sizes
6972         if (vid.support.arb_texture_non_power_of_two)
6973         {
6974                 screentexturewidth = r_refdef.view.width;
6975                 screentextureheight = r_refdef.view.height;
6976                 bloomtexturewidth = r_bloomstate.bloomwidth;
6977                 bloomtextureheight = r_bloomstate.bloomheight;
6978         }
6979         else
6980         {
6981                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6982                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6983                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6984                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6985         }
6986
6987         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))
6988         {
6989                 Cvar_SetValueQuick(&r_hdr, 0);
6990                 Cvar_SetValueQuick(&r_bloom, 0);
6991                 Cvar_SetValueQuick(&r_motionblur, 0);
6992                 Cvar_SetValueQuick(&r_damageblur, 0);
6993         }
6994
6995         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)))
6996                 screentexturewidth = screentextureheight = 0;
6997         if (!r_hdr.integer && !r_bloom.integer)
6998                 bloomtexturewidth = bloomtextureheight = 0;
6999
7000         // allocate textures as needed
7001         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7002         {
7003                 if (r_bloomstate.texture_screen)
7004                         R_FreeTexture(r_bloomstate.texture_screen);
7005                 r_bloomstate.texture_screen = NULL;
7006                 r_bloomstate.screentexturewidth = screentexturewidth;
7007                 r_bloomstate.screentextureheight = screentextureheight;
7008                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7009                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7010         }
7011         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7012         {
7013                 if (r_bloomstate.texture_bloom)
7014                         R_FreeTexture(r_bloomstate.texture_bloom);
7015                 r_bloomstate.texture_bloom = NULL;
7016                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7017                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7018                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7019                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7020         }
7021
7022         // when doing a reduced render (HDR) we want to use a smaller area
7023         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7024         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7025         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7026         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7027         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7028
7029         // set up a texcoord array for the full resolution screen image
7030         // (we have to keep this around to copy back during final render)
7031         r_bloomstate.screentexcoord2f[0] = 0;
7032         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7033         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7034         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7035         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7036         r_bloomstate.screentexcoord2f[5] = 0;
7037         r_bloomstate.screentexcoord2f[6] = 0;
7038         r_bloomstate.screentexcoord2f[7] = 0;
7039
7040         // set up a texcoord array for the reduced resolution bloom image
7041         // (which will be additive blended over the screen image)
7042         r_bloomstate.bloomtexcoord2f[0] = 0;
7043         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7044         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7045         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7046         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7047         r_bloomstate.bloomtexcoord2f[5] = 0;
7048         r_bloomstate.bloomtexcoord2f[6] = 0;
7049         r_bloomstate.bloomtexcoord2f[7] = 0;
7050
7051         if (r_hdr.integer || r_bloom.integer)
7052         {
7053                 r_bloomstate.enabled = true;
7054                 r_bloomstate.hdr = r_hdr.integer != 0;
7055         }
7056
7057         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);
7058 }
7059
7060 void R_Bloom_CopyBloomTexture(float colorscale)
7061 {
7062         r_refdef.stats.bloom++;
7063
7064         // scale down screen texture to the bloom texture size
7065         CHECKGLERROR
7066         R_SetViewport(&r_bloomstate.viewport);
7067         GL_BlendFunc(GL_ONE, GL_ZERO);
7068         GL_Color(colorscale, colorscale, colorscale, 1);
7069         // TODO: optimize with multitexture or GLSL
7070         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7071         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7072         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7073         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7074
7075         // we now have a bloom image in the framebuffer
7076         // copy it into the bloom image texture for later processing
7077         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);
7078         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7079 }
7080
7081 void R_Bloom_CopyHDRTexture(void)
7082 {
7083         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);
7084         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7085 }
7086
7087 void R_Bloom_MakeTexture(void)
7088 {
7089         int x, range, dir;
7090         float xoffset, yoffset, r, brighten;
7091
7092         r_refdef.stats.bloom++;
7093
7094         R_ResetViewRendering2D();
7095         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7096         R_Mesh_ColorPointer(NULL, 0, 0);
7097
7098         // we have a bloom image in the framebuffer
7099         CHECKGLERROR
7100         R_SetViewport(&r_bloomstate.viewport);
7101
7102         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7103         {
7104                 x *= 2;
7105                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7106                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7107                 GL_Color(r, r, r, 1);
7108                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7109                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7110                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7111                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7112
7113                 // copy the vertically blurred bloom view to a texture
7114                 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);
7115                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7116         }
7117
7118         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7119         brighten = r_bloom_brighten.value;
7120         if (r_hdr.integer)
7121                 brighten *= r_hdr_range.value;
7122         brighten = sqrt(brighten);
7123         if(range >= 1)
7124                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7125         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7126         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7127
7128         for (dir = 0;dir < 2;dir++)
7129         {
7130                 // blend on at multiple vertical offsets to achieve a vertical blur
7131                 // TODO: do offset blends using GLSL
7132                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7133                 GL_BlendFunc(GL_ONE, GL_ZERO);
7134                 for (x = -range;x <= range;x++)
7135                 {
7136                         if (!dir){xoffset = 0;yoffset = x;}
7137                         else {xoffset = x;yoffset = 0;}
7138                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7139                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7140                         // compute a texcoord array with the specified x and y offset
7141                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7142                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7143                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7144                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7145                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7146                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7147                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7148                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7149                         // this r value looks like a 'dot' particle, fading sharply to
7150                         // black at the edges
7151                         // (probably not realistic but looks good enough)
7152                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7153                         //r = brighten/(range*2+1);
7154                         r = brighten / (range * 2 + 1);
7155                         if(range >= 1)
7156                                 r *= (1 - x*x/(float)(range*range));
7157                         GL_Color(r, r, r, 1);
7158                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7159                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7160                         GL_BlendFunc(GL_ONE, GL_ONE);
7161                 }
7162
7163                 // copy the vertically blurred bloom view to a texture
7164                 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);
7165                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7166         }
7167
7168         // apply subtract last
7169         // (just like it would be in a GLSL shader)
7170         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7171         {
7172                 GL_BlendFunc(GL_ONE, GL_ZERO);
7173                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7174                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7175                 GL_Color(1, 1, 1, 1);
7176                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7177                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7178
7179                 GL_BlendFunc(GL_ONE, GL_ONE);
7180                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7181                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7182                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7183                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7184                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7185                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7186                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7187
7188                 // copy the darkened bloom view to a texture
7189                 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);
7190                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7191         }
7192 }
7193
7194 void R_HDR_RenderBloomTexture(void)
7195 {
7196         int oldwidth, oldheight;
7197         float oldcolorscale;
7198
7199         oldcolorscale = r_refdef.view.colorscale;
7200         oldwidth = r_refdef.view.width;
7201         oldheight = r_refdef.view.height;
7202         r_refdef.view.width = r_bloomstate.bloomwidth;
7203         r_refdef.view.height = r_bloomstate.bloomheight;
7204
7205         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7206         // TODO: add exposure compensation features
7207         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7208
7209         r_refdef.view.showdebug = false;
7210         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7211
7212         R_ResetViewRendering3D();
7213
7214         R_ClearScreen(r_refdef.fogenabled);
7215         if (r_timereport_active)
7216                 R_TimeReport("HDRclear");
7217
7218         R_View_Update();
7219         if (r_timereport_active)
7220                 R_TimeReport("visibility");
7221
7222         // only do secondary renders with HDR if r_hdr is 2 or higher
7223         r_waterstate.numwaterplanes = 0;
7224         if (r_waterstate.enabled && r_hdr.integer >= 2)
7225                 R_RenderWaterPlanes();
7226
7227         r_refdef.view.showdebug = true;
7228         R_RenderScene();
7229         r_waterstate.numwaterplanes = 0;
7230
7231         R_ResetViewRendering2D();
7232
7233         R_Bloom_CopyHDRTexture();
7234         R_Bloom_MakeTexture();
7235
7236         // restore the view settings
7237         r_refdef.view.width = oldwidth;
7238         r_refdef.view.height = oldheight;
7239         r_refdef.view.colorscale = oldcolorscale;
7240
7241         R_ResetViewRendering3D();
7242
7243         R_ClearScreen(r_refdef.fogenabled);
7244         if (r_timereport_active)
7245                 R_TimeReport("viewclear");
7246 }
7247
7248 static void R_BlendView(void)
7249 {
7250         unsigned int permutation;
7251         float uservecs[4][4];
7252
7253         switch (vid.renderpath)
7254         {
7255         case RENDERPATH_GL20:
7256         case RENDERPATH_CGGL:
7257                 permutation =
7258                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7259                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7260                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7261                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7262                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7263
7264                 if (r_bloomstate.texture_screen)
7265                 {
7266                         // make sure the buffer is available
7267                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7268
7269                         R_ResetViewRendering2D();
7270                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7271                         R_Mesh_ColorPointer(NULL, 0, 0);
7272
7273                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7274                         {
7275                                 // declare variables
7276                                 float speed;
7277                                 static float avgspeed;
7278
7279                                 speed = VectorLength(cl.movement_velocity);
7280
7281                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7282                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7283
7284                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7285                                 speed = bound(0, speed, 1);
7286                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7287
7288                                 // calculate values into a standard alpha
7289                                 cl.motionbluralpha = 1 - exp(-
7290                                                 (
7291                                                  (r_motionblur.value * speed / 80)
7292                                                  +
7293                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7294                                                 )
7295                                                 /
7296                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7297                                            );
7298
7299                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7300                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7301                                 // apply the blur
7302                                 if (cl.motionbluralpha > 0)
7303                                 {
7304                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7305                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7306                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7307                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7308                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7309                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7310                                 }
7311                         }
7312
7313                         // copy view into the screen texture
7314                         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);
7315                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7316                 }
7317                 else if (!r_bloomstate.texture_bloom)
7318                 {
7319                         // we may still have to do view tint...
7320                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7321                         {
7322                                 // apply a color tint to the whole view
7323                                 R_ResetViewRendering2D();
7324                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7325                                 R_Mesh_ColorPointer(NULL, 0, 0);
7326                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7327                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7328                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7329                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7330                         }
7331                         break; // no screen processing, no bloom, skip it
7332                 }
7333
7334                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7335                 {
7336                         // render simple bloom effect
7337                         // copy the screen and shrink it and darken it for the bloom process
7338                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7339                         // make the bloom texture
7340                         R_Bloom_MakeTexture();
7341                 }
7342
7343 #if _MSC_VER >= 1400
7344 #define sscanf sscanf_s
7345 #endif
7346                 memset(uservecs, 0, sizeof(uservecs));
7347                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7348                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7349                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7350                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7351
7352                 R_ResetViewRendering2D();
7353                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7354                 R_Mesh_ColorPointer(NULL, 0, 0);
7355                 GL_Color(1, 1, 1, 1);
7356                 GL_BlendFunc(GL_ONE, GL_ZERO);
7357                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7358                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7359
7360                 switch(vid.renderpath)
7361                 {
7362                 case RENDERPATH_GL20:
7363                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7364                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7365                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7366                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7367                         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]);
7368                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7369                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7370                         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]);
7371                         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]);
7372                         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]);
7373                         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]);
7374                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7375                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7376                         break;
7377                 case RENDERPATH_CGGL:
7378 #ifdef SUPPORTCG
7379                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7380                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7381                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7382                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7383                         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
7384                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7385                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7386                         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
7387                         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
7388                         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
7389                         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
7390                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7391                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7392 #endif
7393                         break;
7394                 default:
7395                         break;
7396                 }
7397                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7398                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7399                 break;
7400         case RENDERPATH_GL13:
7401         case RENDERPATH_GL11:
7402                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7403                 {
7404                         // apply a color tint to the whole view
7405                         R_ResetViewRendering2D();
7406                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7407                         R_Mesh_ColorPointer(NULL, 0, 0);
7408                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7409                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7410                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7411                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7412                 }
7413                 break;
7414         }
7415 }
7416
7417 matrix4x4_t r_waterscrollmatrix;
7418
7419 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7420 {
7421         if (r_refdef.fog_density)
7422         {
7423                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7424                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7425                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7426
7427                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7428                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7429                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7430                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7431
7432                 {
7433                         vec3_t fogvec;
7434                         VectorCopy(r_refdef.fogcolor, fogvec);
7435                         //   color.rgb *= ContrastBoost * SceneBrightness;
7436                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7437                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7438                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7439                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7440                 }
7441         }
7442 }
7443
7444 void R_UpdateVariables(void)
7445 {
7446         R_Textures_Frame();
7447
7448         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7449
7450         r_refdef.farclip = r_farclip_base.value;
7451         if (r_refdef.scene.worldmodel)
7452                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7453         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7454
7455         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7456                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7457         r_refdef.polygonfactor = 0;
7458         r_refdef.polygonoffset = 0;
7459         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7460         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7461
7462         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7463         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7464         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7465         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7466         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7467         if (r_showsurfaces.integer)
7468         {
7469                 r_refdef.scene.rtworld = false;
7470                 r_refdef.scene.rtworldshadows = false;
7471                 r_refdef.scene.rtdlight = false;
7472                 r_refdef.scene.rtdlightshadows = false;
7473                 r_refdef.lightmapintensity = 0;
7474         }
7475
7476         if (gamemode == GAME_NEHAHRA)
7477         {
7478                 if (gl_fogenable.integer)
7479                 {
7480                         r_refdef.oldgl_fogenable = true;
7481                         r_refdef.fog_density = gl_fogdensity.value;
7482                         r_refdef.fog_red = gl_fogred.value;
7483                         r_refdef.fog_green = gl_foggreen.value;
7484                         r_refdef.fog_blue = gl_fogblue.value;
7485                         r_refdef.fog_alpha = 1;
7486                         r_refdef.fog_start = 0;
7487                         r_refdef.fog_end = gl_skyclip.value;
7488                         r_refdef.fog_height = 1<<30;
7489                         r_refdef.fog_fadedepth = 128;
7490                 }
7491                 else if (r_refdef.oldgl_fogenable)
7492                 {
7493                         r_refdef.oldgl_fogenable = false;
7494                         r_refdef.fog_density = 0;
7495                         r_refdef.fog_red = 0;
7496                         r_refdef.fog_green = 0;
7497                         r_refdef.fog_blue = 0;
7498                         r_refdef.fog_alpha = 0;
7499                         r_refdef.fog_start = 0;
7500                         r_refdef.fog_end = 0;
7501                         r_refdef.fog_height = 1<<30;
7502                         r_refdef.fog_fadedepth = 128;
7503                 }
7504         }
7505
7506         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7507         r_refdef.fog_start = max(0, r_refdef.fog_start);
7508         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7509
7510         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7511
7512         if (r_refdef.fog_density && r_drawfog.integer)
7513         {
7514                 r_refdef.fogenabled = true;
7515                 // this is the point where the fog reaches 0.9986 alpha, which we
7516                 // consider a good enough cutoff point for the texture
7517                 // (0.9986 * 256 == 255.6)
7518                 if (r_fog_exp2.integer)
7519                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7520                 else
7521                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7522                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7523                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7524                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7525                 // fog color was already set
7526                 // update the fog texture
7527                 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)
7528                         R_BuildFogTexture();
7529         }
7530         else
7531                 r_refdef.fogenabled = false;
7532
7533         switch(vid.renderpath)
7534         {
7535         case RENDERPATH_GL20:
7536         case RENDERPATH_CGGL:
7537                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7538                 {
7539                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7540                         {
7541                                 // build GLSL gamma texture
7542 #define RAMPWIDTH 256
7543                                 unsigned short ramp[RAMPWIDTH * 3];
7544                                 unsigned char rampbgr[RAMPWIDTH][4];
7545                                 int i;
7546
7547                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7548
7549                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7550                                 for(i = 0; i < RAMPWIDTH; ++i)
7551                                 {
7552                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7553                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7554                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7555                                         rampbgr[i][3] = 0;
7556                                 }
7557                                 if (r_texture_gammaramps)
7558                                 {
7559                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7560                                 }
7561                                 else
7562                                 {
7563                                         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);
7564                                 }
7565                         }
7566                 }
7567                 else
7568                 {
7569                         // remove GLSL gamma texture
7570                 }
7571                 break;
7572         case RENDERPATH_GL13:
7573         case RENDERPATH_GL11:
7574                 break;
7575         }
7576 }
7577
7578 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7579 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7580 /*
7581 ================
7582 R_SelectScene
7583 ================
7584 */
7585 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7586         if( scenetype != r_currentscenetype ) {
7587                 // store the old scenetype
7588                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7589                 r_currentscenetype = scenetype;
7590                 // move in the new scene
7591                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7592         }
7593 }
7594
7595 /*
7596 ================
7597 R_GetScenePointer
7598 ================
7599 */
7600 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7601 {
7602         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7603         if( scenetype == r_currentscenetype ) {
7604                 return &r_refdef.scene;
7605         } else {
7606                 return &r_scenes_store[ scenetype ];
7607         }
7608 }
7609
7610 /*
7611 ================
7612 R_RenderView
7613 ================
7614 */
7615 void R_RenderView(void)
7616 {
7617         if (r_timereport_active)
7618                 R_TimeReport("start");
7619         r_textureframe++; // used only by R_GetCurrentTexture
7620         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7621
7622         if (!r_drawentities.integer)
7623                 r_refdef.scene.numentities = 0;
7624
7625         R_AnimCache_ClearCache();
7626         R_FrameData_NewFrame();
7627
7628         if (r_refdef.view.isoverlay)
7629         {
7630                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7631                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7632                 R_TimeReport("depthclear");
7633
7634                 r_refdef.view.showdebug = false;
7635
7636                 r_waterstate.enabled = false;
7637                 r_waterstate.numwaterplanes = 0;
7638
7639                 R_RenderScene();
7640
7641                 CHECKGLERROR
7642                 return;
7643         }
7644
7645         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7646                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7647
7648         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7649
7650         // break apart the view matrix into vectors for various purposes
7651         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7652         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7653         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7654         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7655         // make an inverted copy of the view matrix for tracking sprites
7656         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7657
7658         R_Shadow_UpdateWorldLightSelection();
7659
7660         R_Bloom_StartFrame();
7661         R_Water_StartFrame();
7662
7663         CHECKGLERROR
7664         if (r_timereport_active)
7665                 R_TimeReport("viewsetup");
7666
7667         R_ResetViewRendering3D();
7668
7669         if (r_refdef.view.clear || r_refdef.fogenabled)
7670         {
7671                 R_ClearScreen(r_refdef.fogenabled);
7672                 if (r_timereport_active)
7673                         R_TimeReport("viewclear");
7674         }
7675         r_refdef.view.clear = true;
7676
7677         // this produces a bloom texture to be used in R_BlendView() later
7678         if (r_hdr.integer && r_bloomstate.bloomwidth)
7679         {
7680                 R_HDR_RenderBloomTexture();
7681                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
7682                 r_textureframe++; // used only by R_GetCurrentTexture
7683         }
7684
7685         r_refdef.view.showdebug = true;
7686
7687         R_View_Update();
7688         if (r_timereport_active)
7689                 R_TimeReport("visibility");
7690
7691         r_waterstate.numwaterplanes = 0;
7692         if (r_waterstate.enabled)
7693                 R_RenderWaterPlanes();
7694
7695         R_RenderScene();
7696         r_waterstate.numwaterplanes = 0;
7697
7698         R_BlendView();
7699         if (r_timereport_active)
7700                 R_TimeReport("blendview");
7701
7702         GL_Scissor(0, 0, vid.width, vid.height);
7703         GL_ScissorTest(false);
7704         CHECKGLERROR
7705 }
7706
7707 void R_RenderWaterPlanes(void)
7708 {
7709         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7710         {
7711                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7712                 if (r_timereport_active)
7713                         R_TimeReport("waterworld");
7714         }
7715
7716         // don't let sound skip if going slow
7717         if (r_refdef.scene.extraupdate)
7718                 S_ExtraUpdate ();
7719
7720         R_DrawModelsAddWaterPlanes();
7721         if (r_timereport_active)
7722                 R_TimeReport("watermodels");
7723
7724         if (r_waterstate.numwaterplanes)
7725         {
7726                 R_Water_ProcessPlanes();
7727                 if (r_timereport_active)
7728                         R_TimeReport("waterscenes");
7729         }
7730 }
7731
7732 extern void R_DrawLightningBeams (void);
7733 extern void VM_CL_AddPolygonsToMeshQueue (void);
7734 extern void R_DrawPortals (void);
7735 extern cvar_t cl_locs_show;
7736 static void R_DrawLocs(void);
7737 static void R_DrawEntityBBoxes(void);
7738 static void R_DrawModelDecals(void);
7739 extern cvar_t cl_decals_newsystem;
7740 extern qboolean r_shadow_usingdeferredprepass;
7741 void R_RenderScene(void)
7742 {
7743         r_refdef.stats.renders++;
7744
7745         R_UpdateFogColor();
7746
7747         // don't let sound skip if going slow
7748         if (r_refdef.scene.extraupdate)
7749                 S_ExtraUpdate ();
7750
7751         R_MeshQueue_BeginScene();
7752
7753         R_SkyStartFrame();
7754
7755         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);
7756
7757         if (cl.csqc_vidvars.drawworld)
7758         {
7759                 // don't let sound skip if going slow
7760                 if (r_refdef.scene.extraupdate)
7761                         S_ExtraUpdate ();
7762
7763                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7764                 {
7765                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7766                         if (r_timereport_active)
7767                                 R_TimeReport("worldsky");
7768                 }
7769
7770                 if (R_DrawBrushModelsSky() && r_timereport_active)
7771                         R_TimeReport("bmodelsky");
7772
7773                 if (skyrendermasked && skyrenderlater)
7774                 {
7775                         // we have to force off the water clipping plane while rendering sky
7776                         R_SetupView(false);
7777                         R_Sky();
7778                         R_SetupView(true);
7779                         if (r_timereport_active)
7780                                 R_TimeReport("sky");
7781                 }
7782         }
7783
7784         R_AnimCache_CacheVisibleEntities();
7785         if (r_timereport_active)
7786                 R_TimeReport("animation");
7787
7788         R_Shadow_PrepareLights();
7789         if (r_timereport_active)
7790                 R_TimeReport("preparelights");
7791
7792         if (r_shadow_usingdeferredprepass)
7793                 R_Shadow_DrawPrepass();
7794
7795         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7796         {
7797                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7798                 if (r_timereport_active)
7799                         R_TimeReport("worlddepth");
7800         }
7801         if (r_depthfirst.integer >= 2)
7802         {
7803                 R_DrawModelsDepth();
7804                 if (r_timereport_active)
7805                         R_TimeReport("modeldepth");
7806         }
7807
7808         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7809         {
7810                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7811                 if (r_timereport_active)
7812                         R_TimeReport("world");
7813         }
7814
7815         // don't let sound skip if going slow
7816         if (r_refdef.scene.extraupdate)
7817                 S_ExtraUpdate ();
7818
7819         R_DrawModels();
7820         if (r_timereport_active)
7821                 R_TimeReport("models");
7822
7823         // don't let sound skip if going slow
7824         if (r_refdef.scene.extraupdate)
7825                 S_ExtraUpdate ();
7826
7827         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7828         {
7829                 R_DrawModelShadows();
7830                 R_ResetViewRendering3D();
7831                 // don't let sound skip if going slow
7832                 if (r_refdef.scene.extraupdate)
7833                         S_ExtraUpdate ();
7834         }
7835
7836         if (!r_shadow_usingdeferredprepass)
7837         {
7838                 R_Shadow_DrawLights();
7839                 if (r_timereport_active)
7840                         R_TimeReport("rtlights");
7841         }
7842
7843         // don't let sound skip if going slow
7844         if (r_refdef.scene.extraupdate)
7845                 S_ExtraUpdate ();
7846
7847         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7848         {
7849                 R_DrawModelShadows();
7850                 R_ResetViewRendering3D();
7851                 // don't let sound skip if going slow
7852                 if (r_refdef.scene.extraupdate)
7853                         S_ExtraUpdate ();
7854         }
7855
7856         if (cl.csqc_vidvars.drawworld)
7857         {
7858                 if (cl_decals_newsystem.integer)
7859                 {
7860                         R_DrawModelDecals();
7861                         if (r_timereport_active)
7862                                 R_TimeReport("modeldecals");
7863                 }
7864                 else
7865                 {
7866                         R_DrawDecals();
7867                         if (r_timereport_active)
7868                                 R_TimeReport("decals");
7869                 }
7870
7871                 R_DrawParticles();
7872                 if (r_timereport_active)
7873                         R_TimeReport("particles");
7874
7875                 R_DrawExplosions();
7876                 if (r_timereport_active)
7877                         R_TimeReport("explosions");
7878
7879                 R_DrawLightningBeams();
7880                 if (r_timereport_active)
7881                         R_TimeReport("lightning");
7882         }
7883
7884         VM_CL_AddPolygonsToMeshQueue();
7885
7886         if (r_refdef.view.showdebug)
7887         {
7888                 if (cl_locs_show.integer)
7889                 {
7890                         R_DrawLocs();
7891                         if (r_timereport_active)
7892                                 R_TimeReport("showlocs");
7893                 }
7894
7895                 if (r_drawportals.integer)
7896                 {
7897                         R_DrawPortals();
7898                         if (r_timereport_active)
7899                                 R_TimeReport("portals");
7900                 }
7901
7902                 if (r_showbboxes.value > 0)
7903                 {
7904                         R_DrawEntityBBoxes();
7905                         if (r_timereport_active)
7906                                 R_TimeReport("bboxes");
7907                 }
7908         }
7909
7910         R_MeshQueue_RenderTransparent();
7911         if (r_timereport_active)
7912                 R_TimeReport("drawtrans");
7913
7914         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))
7915         {
7916                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7917                 if (r_timereport_active)
7918                         R_TimeReport("worlddebug");
7919                 R_DrawModelsDebug();
7920                 if (r_timereport_active)
7921                         R_TimeReport("modeldebug");
7922         }
7923
7924         if (cl.csqc_vidvars.drawworld)
7925         {
7926                 R_Shadow_DrawCoronas();
7927                 if (r_timereport_active)
7928                         R_TimeReport("coronas");
7929         }
7930
7931         // don't let sound skip if going slow
7932         if (r_refdef.scene.extraupdate)
7933                 S_ExtraUpdate ();
7934
7935         R_ResetViewRendering2D();
7936 }
7937
7938 static const unsigned short bboxelements[36] =
7939 {
7940         5, 1, 3, 5, 3, 7,
7941         6, 2, 0, 6, 0, 4,
7942         7, 3, 2, 7, 2, 6,
7943         4, 0, 1, 4, 1, 5,
7944         4, 5, 7, 4, 7, 6,
7945         1, 0, 2, 1, 2, 3,
7946 };
7947
7948 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7949 {
7950         int i;
7951         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7952
7953         RSurf_ActiveWorldEntity();
7954
7955         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7956         GL_DepthMask(false);
7957         GL_DepthRange(0, 1);
7958         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7959         R_Mesh_ResetTextureState();
7960
7961         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7962         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7963         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7964         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7965         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7966         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7967         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7968         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7969         R_FillColors(color4f, 8, cr, cg, cb, ca);
7970         if (r_refdef.fogenabled)
7971         {
7972                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7973                 {
7974                         f1 = RSurf_FogVertex(v);
7975                         f2 = 1 - f1;
7976                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7977                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7978                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7979                 }
7980         }
7981         R_Mesh_VertexPointer(vertex3f, 0, 0);
7982         R_Mesh_ColorPointer(color4f, 0, 0);
7983         R_Mesh_ResetTextureState();
7984         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7985         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
7986 }
7987
7988 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7989 {
7990         int i;
7991         float color[4];
7992         prvm_edict_t *edict;
7993         prvm_prog_t *prog_save = prog;
7994
7995         // this function draws bounding boxes of server entities
7996         if (!sv.active)
7997                 return;
7998
7999         GL_CullFace(GL_NONE);
8000         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8001
8002         prog = 0;
8003         SV_VM_Begin();
8004         for (i = 0;i < numsurfaces;i++)
8005         {
8006                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8007                 switch ((int)edict->fields.server->solid)
8008                 {
8009                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8010                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8011                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8012                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8013                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8014                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8015                 }
8016                 color[3] *= r_showbboxes.value;
8017                 color[3] = bound(0, color[3], 1);
8018                 GL_DepthTest(!r_showdisabledepthtest.integer);
8019                 GL_CullFace(r_refdef.view.cullface_front);
8020                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8021         }
8022         SV_VM_End();
8023         prog = prog_save;
8024 }
8025
8026 static void R_DrawEntityBBoxes(void)
8027 {
8028         int i;
8029         prvm_edict_t *edict;
8030         vec3_t center;
8031         prvm_prog_t *prog_save = prog;
8032
8033         // this function draws bounding boxes of server entities
8034         if (!sv.active)
8035                 return;
8036
8037         prog = 0;
8038         SV_VM_Begin();
8039         for (i = 0;i < prog->num_edicts;i++)
8040         {
8041                 edict = PRVM_EDICT_NUM(i);
8042                 if (edict->priv.server->free)
8043                         continue;
8044                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8045                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8046                         continue;
8047                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8048                         continue;
8049                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8050                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8051         }
8052         SV_VM_End();
8053         prog = prog_save;
8054 }
8055
8056 static const int nomodelelement3i[24] =
8057 {
8058         5, 2, 0,
8059         5, 1, 2,
8060         5, 0, 3,
8061         5, 3, 1,
8062         0, 2, 4,
8063         2, 1, 4,
8064         3, 0, 4,
8065         1, 3, 4
8066 };
8067
8068 static const unsigned short nomodelelement3s[24] =
8069 {
8070         5, 2, 0,
8071         5, 1, 2,
8072         5, 0, 3,
8073         5, 3, 1,
8074         0, 2, 4,
8075         2, 1, 4,
8076         3, 0, 4,
8077         1, 3, 4
8078 };
8079
8080 static const float nomodelvertex3f[6*3] =
8081 {
8082         -16,   0,   0,
8083          16,   0,   0,
8084           0, -16,   0,
8085           0,  16,   0,
8086           0,   0, -16,
8087           0,   0,  16
8088 };
8089
8090 static const float nomodelcolor4f[6*4] =
8091 {
8092         0.0f, 0.0f, 0.5f, 1.0f,
8093         0.0f, 0.0f, 0.5f, 1.0f,
8094         0.0f, 0.5f, 0.0f, 1.0f,
8095         0.0f, 0.5f, 0.0f, 1.0f,
8096         0.5f, 0.0f, 0.0f, 1.0f,
8097         0.5f, 0.0f, 0.0f, 1.0f
8098 };
8099
8100 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8101 {
8102         int i;
8103         float f1, f2, *c;
8104         float color4f[6*4];
8105
8106         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);
8107
8108         // this is only called once per entity so numsurfaces is always 1, and
8109         // surfacelist is always {0}, so this code does not handle batches
8110
8111         if (rsurface.ent_flags & RENDER_ADDITIVE)
8112         {
8113                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8114                 GL_DepthMask(false);
8115         }
8116         else if (rsurface.colormod[3] < 1)
8117         {
8118                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8119                 GL_DepthMask(false);
8120         }
8121         else
8122         {
8123                 GL_BlendFunc(GL_ONE, GL_ZERO);
8124                 GL_DepthMask(true);
8125         }
8126         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8127         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8128         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8129         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8130         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8131         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8132         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8133         R_Mesh_ColorPointer(color4f, 0, 0);
8134         for (i = 0, c = color4f;i < 6;i++, c += 4)
8135         {
8136                 c[0] *= rsurface.colormod[0];
8137                 c[1] *= rsurface.colormod[1];
8138                 c[2] *= rsurface.colormod[2];
8139                 c[3] *= rsurface.colormod[3];
8140         }
8141         if (r_refdef.fogenabled)
8142         {
8143                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8144                 {
8145                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8146                         f2 = 1 - f1;
8147                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8148                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8149                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8150                 }
8151         }
8152         R_Mesh_ResetTextureState();
8153         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8154 }
8155
8156 void R_DrawNoModel(entity_render_t *ent)
8157 {
8158         vec3_t org;
8159         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8160         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8161                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8162         else
8163                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8164 }
8165
8166 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8167 {
8168         vec3_t right1, right2, diff, normal;
8169
8170         VectorSubtract (org2, org1, normal);
8171
8172         // calculate 'right' vector for start
8173         VectorSubtract (r_refdef.view.origin, org1, diff);
8174         CrossProduct (normal, diff, right1);
8175         VectorNormalize (right1);
8176
8177         // calculate 'right' vector for end
8178         VectorSubtract (r_refdef.view.origin, org2, diff);
8179         CrossProduct (normal, diff, right2);
8180         VectorNormalize (right2);
8181
8182         vert[ 0] = org1[0] + width * right1[0];
8183         vert[ 1] = org1[1] + width * right1[1];
8184         vert[ 2] = org1[2] + width * right1[2];
8185         vert[ 3] = org1[0] - width * right1[0];
8186         vert[ 4] = org1[1] - width * right1[1];
8187         vert[ 5] = org1[2] - width * right1[2];
8188         vert[ 6] = org2[0] - width * right2[0];
8189         vert[ 7] = org2[1] - width * right2[1];
8190         vert[ 8] = org2[2] - width * right2[2];
8191         vert[ 9] = org2[0] + width * right2[0];
8192         vert[10] = org2[1] + width * right2[1];
8193         vert[11] = org2[2] + width * right2[2];
8194 }
8195
8196 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)
8197 {
8198         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8199         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8200         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8201         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8202         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8203         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8204         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8205         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8206         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8207         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8208         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8209         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8210 }
8211
8212 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8213 {
8214         int i;
8215         float *vertex3f;
8216         float v[3];
8217         VectorSet(v, x, y, z);
8218         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8219                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8220                         break;
8221         if (i == mesh->numvertices)
8222         {
8223                 if (mesh->numvertices < mesh->maxvertices)
8224                 {
8225                         VectorCopy(v, vertex3f);
8226                         mesh->numvertices++;
8227                 }
8228                 return mesh->numvertices;
8229         }
8230         else
8231                 return i;
8232 }
8233
8234 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8235 {
8236         int i;
8237         int *e, element[3];
8238         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8239         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8240         e = mesh->element3i + mesh->numtriangles * 3;
8241         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8242         {
8243                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8244                 if (mesh->numtriangles < mesh->maxtriangles)
8245                 {
8246                         *e++ = element[0];
8247                         *e++ = element[1];
8248                         *e++ = element[2];
8249                         mesh->numtriangles++;
8250                 }
8251                 element[1] = element[2];
8252         }
8253 }
8254
8255 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8256 {
8257         int i;
8258         int *e, element[3];
8259         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8260         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8261         e = mesh->element3i + mesh->numtriangles * 3;
8262         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8263         {
8264                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8265                 if (mesh->numtriangles < mesh->maxtriangles)
8266                 {
8267                         *e++ = element[0];
8268                         *e++ = element[1];
8269                         *e++ = element[2];
8270                         mesh->numtriangles++;
8271                 }
8272                 element[1] = element[2];
8273         }
8274 }
8275
8276 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8277 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8278 {
8279         int planenum, planenum2;
8280         int w;
8281         int tempnumpoints;
8282         mplane_t *plane, *plane2;
8283         double maxdist;
8284         double temppoints[2][256*3];
8285         // figure out how large a bounding box we need to properly compute this brush
8286         maxdist = 0;
8287         for (w = 0;w < numplanes;w++)
8288                 maxdist = max(maxdist, fabs(planes[w].dist));
8289         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8290         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8291         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8292         {
8293                 w = 0;
8294                 tempnumpoints = 4;
8295                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8296                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8297                 {
8298                         if (planenum2 == planenum)
8299                                 continue;
8300                         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);
8301                         w = !w;
8302                 }
8303                 if (tempnumpoints < 3)
8304                         continue;
8305                 // generate elements forming a triangle fan for this polygon
8306                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8307         }
8308 }
8309
8310 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)
8311 {
8312         texturelayer_t *layer;
8313         layer = t->currentlayers + t->currentnumlayers++;
8314         layer->type = type;
8315         layer->depthmask = depthmask;
8316         layer->blendfunc1 = blendfunc1;
8317         layer->blendfunc2 = blendfunc2;
8318         layer->texture = texture;
8319         layer->texmatrix = *matrix;
8320         layer->color[0] = r;
8321         layer->color[1] = g;
8322         layer->color[2] = b;
8323         layer->color[3] = a;
8324 }
8325
8326 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8327 {
8328         double index, f;
8329         index = parms[2] + r_refdef.scene.time * parms[3];
8330         index -= floor(index);
8331         switch (func)
8332         {
8333         default:
8334         case Q3WAVEFUNC_NONE:
8335         case Q3WAVEFUNC_NOISE:
8336         case Q3WAVEFUNC_COUNT:
8337                 f = 0;
8338                 break;
8339         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8340         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8341         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8342         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8343         case Q3WAVEFUNC_TRIANGLE:
8344                 index *= 4;
8345                 f = index - floor(index);
8346                 if (index < 1)
8347                         f = f;
8348                 else if (index < 2)
8349                         f = 1 - f;
8350                 else if (index < 3)
8351                         f = -f;
8352                 else
8353                         f = -(1 - f);
8354                 break;
8355         }
8356         return (float)(parms[0] + parms[1] * f);
8357 }
8358
8359 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8360 {
8361         int w, h, idx;
8362         float f;
8363         float tcmat[12];
8364         matrix4x4_t matrix, temp;
8365         switch(tcmod->tcmod)
8366         {
8367                 case Q3TCMOD_COUNT:
8368                 case Q3TCMOD_NONE:
8369                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8370                                 matrix = r_waterscrollmatrix;
8371                         else
8372                                 matrix = identitymatrix;
8373                         break;
8374                 case Q3TCMOD_ENTITYTRANSLATE:
8375                         // this is used in Q3 to allow the gamecode to control texcoord
8376                         // scrolling on the entity, which is not supported in darkplaces yet.
8377                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8378                         break;
8379                 case Q3TCMOD_ROTATE:
8380                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8381                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8382                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8383                         break;
8384                 case Q3TCMOD_SCALE:
8385                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8386                         break;
8387                 case Q3TCMOD_SCROLL:
8388                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8389                         break;
8390                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8391                         w = (int) tcmod->parms[0];
8392                         h = (int) tcmod->parms[1];
8393                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8394                         f = f - floor(f);
8395                         idx = (int) floor(f * w * h);
8396                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8397                         break;
8398                 case Q3TCMOD_STRETCH:
8399                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8400                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8401                         break;
8402                 case Q3TCMOD_TRANSFORM:
8403                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8404                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8405                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8406                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8407                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8408                         break;
8409                 case Q3TCMOD_TURBULENT:
8410                         // this is handled in the RSurf_PrepareVertices function
8411                         matrix = identitymatrix;
8412                         break;
8413         }
8414         temp = *texmatrix;
8415         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8416 }
8417
8418 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8419 {
8420         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8421         char name[MAX_QPATH];
8422         skinframe_t *skinframe;
8423         unsigned char pixels[296*194];
8424         strlcpy(cache->name, skinname, sizeof(cache->name));
8425         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8426         if (developer_loading.integer)
8427                 Con_Printf("loading %s\n", name);
8428         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8429         if (!skinframe || !skinframe->base)
8430         {
8431                 unsigned char *f;
8432                 fs_offset_t filesize;
8433                 skinframe = NULL;
8434                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8435                 if (f)
8436                 {
8437                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8438                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8439                         Mem_Free(f);
8440                 }
8441         }
8442         cache->skinframe = skinframe;
8443 }
8444
8445 texture_t *R_GetCurrentTexture(texture_t *t)
8446 {
8447         int i;
8448         const entity_render_t *ent = rsurface.entity;
8449         dp_model_t *model = ent->model;
8450         q3shaderinfo_layer_tcmod_t *tcmod;
8451
8452         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8453                 return t->currentframe;
8454         t->update_lastrenderframe = r_textureframe;
8455         t->update_lastrenderentity = (void *)ent;
8456
8457         // switch to an alternate material if this is a q1bsp animated material
8458         {
8459                 texture_t *texture = t;
8460                 int s = rsurface.ent_skinnum;
8461                 if ((unsigned int)s >= (unsigned int)model->numskins)
8462                         s = 0;
8463                 if (model->skinscenes)
8464                 {
8465                         if (model->skinscenes[s].framecount > 1)
8466                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8467                         else
8468                                 s = model->skinscenes[s].firstframe;
8469                 }
8470                 if (s > 0)
8471                         t = t + s * model->num_surfaces;
8472                 if (t->animated)
8473                 {
8474                         // use an alternate animation if the entity's frame is not 0,
8475                         // and only if the texture has an alternate animation
8476                         if (rsurface.ent_alttextures && t->anim_total[1])
8477                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8478                         else
8479                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8480                 }
8481                 texture->currentframe = t;
8482         }
8483
8484         // update currentskinframe to be a qw skin or animation frame
8485         if (rsurface.ent_qwskin >= 0)
8486         {
8487                 i = rsurface.ent_qwskin;
8488                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8489                 {
8490                         r_qwskincache_size = cl.maxclients;
8491                         if (r_qwskincache)
8492                                 Mem_Free(r_qwskincache);
8493                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8494                 }
8495                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8496                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8497                 t->currentskinframe = r_qwskincache[i].skinframe;
8498                 if (t->currentskinframe == NULL)
8499                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8500         }
8501         else if (t->numskinframes >= 2)
8502                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8503         if (t->backgroundnumskinframes >= 2)
8504                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8505
8506         t->currentmaterialflags = t->basematerialflags;
8507         t->currentalpha = rsurface.colormod[3];
8508         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8509                 t->currentalpha *= r_wateralpha.value;
8510         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8511                 t->currentalpha *= t->r_water_wateralpha;
8512         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8513                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8514         if (!(rsurface.ent_flags & RENDER_LIGHT))
8515                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8516         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8517         {
8518                 // pick a model lighting mode
8519                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8520                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8521                 else
8522                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8523         }
8524         if (rsurface.ent_flags & RENDER_ADDITIVE)
8525                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8526         else if (t->currentalpha < 1)
8527                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8528         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8529                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8530         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8531                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8532         if (t->backgroundnumskinframes)
8533                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8534         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8535         {
8536                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8537                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8538         }
8539         else
8540                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8541         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8542                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8543
8544         // there is no tcmod
8545         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8546         {
8547                 t->currenttexmatrix = r_waterscrollmatrix;
8548                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8549         }
8550         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8551         {
8552                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8553                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8554         }
8555
8556         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8557                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8558         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8559                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8560
8561         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8562         if (t->currentskinframe->qpixels)
8563                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8564         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8565         if (!t->basetexture)
8566                 t->basetexture = r_texture_notexture;
8567         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8568         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8569         t->nmaptexture = t->currentskinframe->nmap;
8570         if (!t->nmaptexture)
8571                 t->nmaptexture = r_texture_blanknormalmap;
8572         t->glosstexture = r_texture_black;
8573         t->glowtexture = t->currentskinframe->glow;
8574         t->fogtexture = t->currentskinframe->fog;
8575         if (t->backgroundnumskinframes)
8576         {
8577                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8578                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8579                 t->backgroundglosstexture = r_texture_black;
8580                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8581                 if (!t->backgroundnmaptexture)
8582                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8583         }
8584         else
8585         {
8586                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8587                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8588                 t->backgroundglosstexture = r_texture_black;
8589                 t->backgroundglowtexture = NULL;
8590         }
8591         t->specularpower = r_shadow_glossexponent.value;
8592         // TODO: store reference values for these in the texture?
8593         t->specularscale = 0;
8594         if (r_shadow_gloss.integer > 0)
8595         {
8596                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8597                 {
8598                         if (r_shadow_glossintensity.value > 0)
8599                         {
8600                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8601                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8602                                 t->specularscale = r_shadow_glossintensity.value;
8603                         }
8604                 }
8605                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8606                 {
8607                         t->glosstexture = r_texture_white;
8608                         t->backgroundglosstexture = r_texture_white;
8609                         t->specularscale = r_shadow_gloss2intensity.value;
8610                         t->specularpower = r_shadow_gloss2exponent.value;
8611                 }
8612         }
8613         t->specularscale *= t->specularscalemod;
8614         t->specularpower *= t->specularpowermod;
8615
8616         // lightmaps mode looks bad with dlights using actual texturing, so turn
8617         // off the colormap and glossmap, but leave the normalmap on as it still
8618         // accurately represents the shading involved
8619         if (gl_lightmaps.integer)
8620         {
8621                 t->basetexture = r_texture_grey128;
8622                 t->pantstexture = r_texture_black;
8623                 t->shirttexture = r_texture_black;
8624                 t->nmaptexture = r_texture_blanknormalmap;
8625                 t->glosstexture = r_texture_black;
8626                 t->glowtexture = NULL;
8627                 t->fogtexture = NULL;
8628                 t->backgroundbasetexture = NULL;
8629                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8630                 t->backgroundglosstexture = r_texture_black;
8631                 t->backgroundglowtexture = NULL;
8632                 t->specularscale = 0;
8633                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8634         }
8635
8636         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8637         VectorClear(t->dlightcolor);
8638         t->currentnumlayers = 0;
8639         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8640         {
8641                 int blendfunc1, blendfunc2;
8642                 qboolean depthmask;
8643                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8644                 {
8645                         blendfunc1 = GL_SRC_ALPHA;
8646                         blendfunc2 = GL_ONE;
8647                 }
8648                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8649                 {
8650                         blendfunc1 = GL_SRC_ALPHA;
8651                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8652                 }
8653                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8654                 {
8655                         blendfunc1 = t->customblendfunc[0];
8656                         blendfunc2 = t->customblendfunc[1];
8657                 }
8658                 else
8659                 {
8660                         blendfunc1 = GL_ONE;
8661                         blendfunc2 = GL_ZERO;
8662                 }
8663                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8664                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8665                 {
8666                         // fullbright is not affected by r_refdef.lightmapintensity
8667                         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]);
8668                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8669                                 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]);
8670                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8671                                 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]);
8672                 }
8673                 else
8674                 {
8675                         vec3_t ambientcolor;
8676                         float colorscale;
8677                         // set the color tint used for lights affecting this surface
8678                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8679                         colorscale = 2;
8680                         // q3bsp has no lightmap updates, so the lightstylevalue that
8681                         // would normally be baked into the lightmap must be
8682                         // applied to the color
8683                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8684                         if (model->type == mod_brushq3)
8685                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8686                         colorscale *= r_refdef.lightmapintensity;
8687                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8688                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8689                         // basic lit geometry
8690                         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]);
8691                         // add pants/shirt if needed
8692                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8693                                 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]);
8694                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8695                                 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]);
8696                         // now add ambient passes if needed
8697                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8698                         {
8699                                 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]);
8700                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8701                                         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]);
8702                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8703                                         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]);
8704                         }
8705                 }
8706                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8707                         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]);
8708                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8709                 {
8710                         // if this is opaque use alpha blend which will darken the earlier
8711                         // passes cheaply.
8712                         //
8713                         // if this is an alpha blended material, all the earlier passes
8714                         // were darkened by fog already, so we only need to add the fog
8715                         // color ontop through the fog mask texture
8716                         //
8717                         // if this is an additive blended material, all the earlier passes
8718                         // were darkened by fog already, and we should not add fog color
8719                         // (because the background was not darkened, there is no fog color
8720                         // that was lost behind it).
8721                         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]);
8722                 }
8723         }
8724
8725         return t->currentframe;
8726 }
8727
8728 rsurfacestate_t rsurface;
8729
8730 void R_Mesh_ResizeArrays(int newvertices)
8731 {
8732         float *base;
8733         if (rsurface.array_size >= newvertices)
8734                 return;
8735         if (rsurface.array_modelvertex3f)
8736                 Mem_Free(rsurface.array_modelvertex3f);
8737         rsurface.array_size = (newvertices + 1023) & ~1023;
8738         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8739         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8740         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8741         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8742         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8743         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8744         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8745         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8746         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8747         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8748         rsurface.array_color4f           = base + rsurface.array_size * 27;
8749         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8750 }
8751
8752 void RSurf_ActiveWorldEntity(void)
8753 {
8754         dp_model_t *model = r_refdef.scene.worldmodel;
8755         //if (rsurface.entity == r_refdef.scene.worldentity)
8756         //      return;
8757         rsurface.entity = r_refdef.scene.worldentity;
8758         rsurface.skeleton = NULL;
8759         rsurface.ent_skinnum = 0;
8760         rsurface.ent_qwskin = -1;
8761         rsurface.ent_shadertime = 0;
8762         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8763         if (rsurface.array_size < model->surfmesh.num_vertices)
8764                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8765         rsurface.matrix = identitymatrix;
8766         rsurface.inversematrix = identitymatrix;
8767         rsurface.matrixscale = 1;
8768         rsurface.inversematrixscale = 1;
8769         R_EntityMatrix(&identitymatrix);
8770         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8771         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8772         rsurface.fograngerecip = r_refdef.fograngerecip;
8773         rsurface.fogheightfade = r_refdef.fogheightfade;
8774         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8775         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8776         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8777         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8778         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8779         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8780         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8781         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8782         rsurface.colormod[3] = 1;
8783         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);
8784         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8785         rsurface.frameblend[0].lerp = 1;
8786         rsurface.ent_alttextures = false;
8787         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8788         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8789         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8790         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8791         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8792         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8793         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8794         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8795         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8796         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8797         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8798         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8799         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8800         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8801         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8802         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8803         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8804         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8805         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8806         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8807         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8808         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8809         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8810         rsurface.modelelement3i = model->surfmesh.data_element3i;
8811         rsurface.modelelement3s = model->surfmesh.data_element3s;
8812         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8813         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8814         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8815         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8816         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8817         rsurface.modelsurfaces = model->data_surfaces;
8818         rsurface.generatedvertex = false;
8819         rsurface.vertex3f  = rsurface.modelvertex3f;
8820         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8821         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8822         rsurface.svector3f = rsurface.modelsvector3f;
8823         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8824         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8825         rsurface.tvector3f = rsurface.modeltvector3f;
8826         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8827         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8828         rsurface.normal3f  = rsurface.modelnormal3f;
8829         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8830         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8831         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8832 }
8833
8834 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8835 {
8836         dp_model_t *model = ent->model;
8837         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8838         //      return;
8839         rsurface.entity = (entity_render_t *)ent;
8840         rsurface.skeleton = ent->skeleton;
8841         rsurface.ent_skinnum = ent->skinnum;
8842         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;
8843         rsurface.ent_shadertime = ent->shadertime;
8844         rsurface.ent_flags = ent->flags;
8845         if (rsurface.array_size < model->surfmesh.num_vertices)
8846                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8847         rsurface.matrix = ent->matrix;
8848         rsurface.inversematrix = ent->inversematrix;
8849         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8850         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8851         R_EntityMatrix(&rsurface.matrix);
8852         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8853         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8854         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8855         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8856         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8857         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8858         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8859         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8860         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8861         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8862         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8863         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8864         rsurface.colormod[3] = ent->alpha;
8865         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8866         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8867         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8868         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8869         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8870         if (ent->model->brush.submodel && !prepass)
8871         {
8872                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8873                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8874         }
8875         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8876         {
8877                 if (ent->animcache_vertex3f && !r_framedata_failed)
8878                 {
8879                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8880                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8881                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8882                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8883                 }
8884                 else if (wanttangents)
8885                 {
8886                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8887                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
8888                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
8889                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8890                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
8891                 }
8892                 else if (wantnormals)
8893                 {
8894                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8895                         rsurface.modelsvector3f = NULL;
8896                         rsurface.modeltvector3f = NULL;
8897                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8898                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
8899                 }
8900                 else
8901                 {
8902                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8903                         rsurface.modelsvector3f = NULL;
8904                         rsurface.modeltvector3f = NULL;
8905                         rsurface.modelnormal3f = NULL;
8906                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
8907                 }
8908                 rsurface.modelvertex3f_bufferobject = 0;
8909                 rsurface.modelvertex3f_bufferoffset = 0;
8910                 rsurface.modelsvector3f_bufferobject = 0;
8911                 rsurface.modelsvector3f_bufferoffset = 0;
8912                 rsurface.modeltvector3f_bufferobject = 0;
8913                 rsurface.modeltvector3f_bufferoffset = 0;
8914                 rsurface.modelnormal3f_bufferobject = 0;
8915                 rsurface.modelnormal3f_bufferoffset = 0;
8916                 rsurface.generatedvertex = true;
8917         }
8918         else
8919         {
8920                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8921                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8922                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8923                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8924                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8925                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8926                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8927                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8928                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8929                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8930                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8931                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8932                 rsurface.generatedvertex = false;
8933         }
8934         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8935         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8936         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8937         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8938         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8939         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8940         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8941         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8942         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8943         rsurface.modelelement3i = model->surfmesh.data_element3i;
8944         rsurface.modelelement3s = model->surfmesh.data_element3s;
8945         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8946         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8947         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8948         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8949         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8950         rsurface.modelsurfaces = model->data_surfaces;
8951         rsurface.vertex3f  = rsurface.modelvertex3f;
8952         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8953         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8954         rsurface.svector3f = rsurface.modelsvector3f;
8955         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8956         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8957         rsurface.tvector3f = rsurface.modeltvector3f;
8958         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8959         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8960         rsurface.normal3f  = rsurface.modelnormal3f;
8961         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8962         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8963         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8964 }
8965
8966 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)
8967 {
8968         rsurface.entity = r_refdef.scene.worldentity;
8969         rsurface.skeleton = NULL;
8970         rsurface.ent_skinnum = 0;
8971         rsurface.ent_qwskin = -1;
8972         rsurface.ent_shadertime = shadertime;
8973         rsurface.ent_flags = entflags;
8974         rsurface.modelnum_vertices = numvertices;
8975         rsurface.modelnum_triangles = numtriangles;
8976         if (rsurface.array_size < rsurface.modelnum_vertices)
8977                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
8978         rsurface.matrix = *matrix;
8979         rsurface.inversematrix = *inversematrix;
8980         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8981         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8982         R_EntityMatrix(&rsurface.matrix);
8983         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8984         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8985         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8986         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8987         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8988         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8989         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8990         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8991         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8992         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8993         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8994         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8995         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);
8996         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8997         rsurface.frameblend[0].lerp = 1;
8998         rsurface.ent_alttextures = false;
8999         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9000         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9001         if (wanttangents)
9002         {
9003                 rsurface.modelvertex3f = vertex3f;
9004                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9005                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9006                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9007         }
9008         else if (wantnormals)
9009         {
9010                 rsurface.modelvertex3f = vertex3f;
9011                 rsurface.modelsvector3f = NULL;
9012                 rsurface.modeltvector3f = NULL;
9013                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9014         }
9015         else
9016         {
9017                 rsurface.modelvertex3f = vertex3f;
9018                 rsurface.modelsvector3f = NULL;
9019                 rsurface.modeltvector3f = NULL;
9020                 rsurface.modelnormal3f = NULL;
9021         }
9022         rsurface.modelvertex3f_bufferobject = 0;
9023         rsurface.modelvertex3f_bufferoffset = 0;
9024         rsurface.modelsvector3f_bufferobject = 0;
9025         rsurface.modelsvector3f_bufferoffset = 0;
9026         rsurface.modeltvector3f_bufferobject = 0;
9027         rsurface.modeltvector3f_bufferoffset = 0;
9028         rsurface.modelnormal3f_bufferobject = 0;
9029         rsurface.modelnormal3f_bufferoffset = 0;
9030         rsurface.generatedvertex = true;
9031         rsurface.modellightmapcolor4f  = color4f;
9032         rsurface.modellightmapcolor4f_bufferobject = 0;
9033         rsurface.modellightmapcolor4f_bufferoffset = 0;
9034         rsurface.modeltexcoordtexture2f  = texcoord2f;
9035         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9036         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9037         rsurface.modeltexcoordlightmap2f  = NULL;
9038         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9039         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9040         rsurface.modelelement3i = element3i;
9041         rsurface.modelelement3s = element3s;
9042         rsurface.modelelement3i_bufferobject = 0;
9043         rsurface.modelelement3s_bufferobject = 0;
9044         rsurface.modellightmapoffsets = NULL;
9045         rsurface.modelsurfaces = NULL;
9046         rsurface.vertex3f  = rsurface.modelvertex3f;
9047         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9048         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9049         rsurface.svector3f = rsurface.modelsvector3f;
9050         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9051         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9052         rsurface.tvector3f = rsurface.modeltvector3f;
9053         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9054         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9055         rsurface.normal3f  = rsurface.modelnormal3f;
9056         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9057         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9058         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9059
9060         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9061         {
9062                 if ((wantnormals || wanttangents) && !normal3f)
9063                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9064                 if (wanttangents && !svector3f)
9065                         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);
9066         }
9067 }
9068
9069 float RSurf_FogPoint(const float *v)
9070 {
9071         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9072         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9073         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9074         float FogHeightFade = r_refdef.fogheightfade;
9075         float fogfrac;
9076         unsigned int fogmasktableindex;
9077         if (r_refdef.fogplaneviewabove)
9078                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9079         else
9080                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9081         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9082         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9083 }
9084
9085 float RSurf_FogVertex(const float *v)
9086 {
9087         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9088         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9089         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9090         float FogHeightFade = rsurface.fogheightfade;
9091         float fogfrac;
9092         unsigned int fogmasktableindex;
9093         if (r_refdef.fogplaneviewabove)
9094                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9095         else
9096                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9097         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9098         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9099 }
9100
9101 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9102 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9103 {
9104         int deformindex;
9105         int texturesurfaceindex;
9106         int i, j;
9107         float amplitude;
9108         float animpos;
9109         float scale;
9110         const float *v1, *in_tc;
9111         float *out_tc;
9112         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9113         float waveparms[4];
9114         q3shaderinfo_deform_t *deform;
9115         // 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
9116         if (rsurface.generatedvertex)
9117         {
9118                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9119                         generatenormals = true;
9120                 for (i = 0;i < Q3MAXDEFORMS;i++)
9121                 {
9122                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9123                         {
9124                                 generatetangents = true;
9125                                 generatenormals = true;
9126                         }
9127                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9128                                 generatenormals = true;
9129                 }
9130                 if (generatenormals && !rsurface.modelnormal3f)
9131                 {
9132                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9133                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9134                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9135                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9136                 }
9137                 if (generatetangents && !rsurface.modelsvector3f)
9138                 {
9139                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9140                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9141                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9142                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9143                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9144                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9145                         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);
9146                 }
9147         }
9148         rsurface.vertex3f  = rsurface.modelvertex3f;
9149         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9150         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9151         rsurface.svector3f = rsurface.modelsvector3f;
9152         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9153         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9154         rsurface.tvector3f = rsurface.modeltvector3f;
9155         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9156         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9157         rsurface.normal3f  = rsurface.modelnormal3f;
9158         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9159         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9160         // if vertices are deformed (sprite flares and things in maps, possibly
9161         // water waves, bulges and other deformations), generate them into
9162         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9163         // (may be static model data or generated data for an animated model, or
9164         //  the previous deform pass)
9165         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9166         {
9167                 switch (deform->deform)
9168                 {
9169                 default:
9170                 case Q3DEFORM_PROJECTIONSHADOW:
9171                 case Q3DEFORM_TEXT0:
9172                 case Q3DEFORM_TEXT1:
9173                 case Q3DEFORM_TEXT2:
9174                 case Q3DEFORM_TEXT3:
9175                 case Q3DEFORM_TEXT4:
9176                 case Q3DEFORM_TEXT5:
9177                 case Q3DEFORM_TEXT6:
9178                 case Q3DEFORM_TEXT7:
9179                 case Q3DEFORM_NONE:
9180                         break;
9181                 case Q3DEFORM_AUTOSPRITE:
9182                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9183                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9184                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9185                         VectorNormalize(newforward);
9186                         VectorNormalize(newright);
9187                         VectorNormalize(newup);
9188                         // make deformed versions of only the model vertices used by the specified surfaces
9189                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9190                         {
9191                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9192                                 // a single autosprite surface can contain multiple sprites...
9193                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9194                                 {
9195                                         VectorClear(center);
9196                                         for (i = 0;i < 4;i++)
9197                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9198                                         VectorScale(center, 0.25f, center);
9199                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9200                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9201                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9202                                         for (i = 0;i < 4;i++)
9203                                         {
9204                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9205                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9206                                         }
9207                                 }
9208                                 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);
9209                                 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);
9210                         }
9211                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9212                         rsurface.vertex3f_bufferobject = 0;
9213                         rsurface.vertex3f_bufferoffset = 0;
9214                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9215                         rsurface.svector3f_bufferobject = 0;
9216                         rsurface.svector3f_bufferoffset = 0;
9217                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9218                         rsurface.tvector3f_bufferobject = 0;
9219                         rsurface.tvector3f_bufferoffset = 0;
9220                         rsurface.normal3f = rsurface.array_deformednormal3f;
9221                         rsurface.normal3f_bufferobject = 0;
9222                         rsurface.normal3f_bufferoffset = 0;
9223                         break;
9224                 case Q3DEFORM_AUTOSPRITE2:
9225                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9226                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9227                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9228                         VectorNormalize(newforward);
9229                         VectorNormalize(newright);
9230                         VectorNormalize(newup);
9231                         // make deformed versions of only the model vertices used by the specified surfaces
9232                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9233                         {
9234                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9235                                 const float *v1, *v2;
9236                                 vec3_t start, end;
9237                                 float f, l;
9238                                 struct
9239                                 {
9240                                         float length2;
9241                                         const float *v1;
9242                                         const float *v2;
9243                                 }
9244                                 shortest[2];
9245                                 memset(shortest, 0, sizeof(shortest));
9246                                 // a single autosprite surface can contain multiple sprites...
9247                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9248                                 {
9249                                         VectorClear(center);
9250                                         for (i = 0;i < 4;i++)
9251                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9252                                         VectorScale(center, 0.25f, center);
9253                                         // find the two shortest edges, then use them to define the
9254                                         // axis vectors for rotating around the central axis
9255                                         for (i = 0;i < 6;i++)
9256                                         {
9257                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9258                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9259 #if 0
9260                                                 Debug_PolygonBegin(NULL, 0);
9261                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9262                                                 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);
9263                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9264                                                 Debug_PolygonEnd();
9265 #endif
9266                                                 l = VectorDistance2(v1, v2);
9267                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9268                                                 if (v1[2] != v2[2])
9269                                                         l += (1.0f / 1024.0f);
9270                                                 if (shortest[0].length2 > l || i == 0)
9271                                                 {
9272                                                         shortest[1] = shortest[0];
9273                                                         shortest[0].length2 = l;
9274                                                         shortest[0].v1 = v1;
9275                                                         shortest[0].v2 = v2;
9276                                                 }
9277                                                 else if (shortest[1].length2 > l || i == 1)
9278                                                 {
9279                                                         shortest[1].length2 = l;
9280                                                         shortest[1].v1 = v1;
9281                                                         shortest[1].v2 = v2;
9282                                                 }
9283                                         }
9284                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9285                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9286 #if 0
9287                                         Debug_PolygonBegin(NULL, 0);
9288                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9289                                         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);
9290                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9291                                         Debug_PolygonEnd();
9292 #endif
9293                                         // this calculates the right vector from the shortest edge
9294                                         // and the up vector from the edge midpoints
9295                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9296                                         VectorNormalize(right);
9297                                         VectorSubtract(end, start, up);
9298                                         VectorNormalize(up);
9299                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9300                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9301                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9302                                         VectorNegate(forward, forward);
9303                                         VectorReflect(forward, 0, up, forward);
9304                                         VectorNormalize(forward);
9305                                         CrossProduct(up, forward, newright);
9306                                         VectorNormalize(newright);
9307 #if 0
9308                                         Debug_PolygonBegin(NULL, 0);
9309                                         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);
9310                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9311                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9312                                         Debug_PolygonEnd();
9313 #endif
9314 #if 0
9315                                         Debug_PolygonBegin(NULL, 0);
9316                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9317                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9318                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9319                                         Debug_PolygonEnd();
9320 #endif
9321                                         // rotate the quad around the up axis vector, this is made
9322                                         // especially easy by the fact we know the quad is flat,
9323                                         // so we only have to subtract the center position and
9324                                         // measure distance along the right vector, and then
9325                                         // multiply that by the newright vector and add back the
9326                                         // center position
9327                                         // we also need to subtract the old position to undo the
9328                                         // displacement from the center, which we do with a
9329                                         // DotProduct, the subtraction/addition of center is also
9330                                         // optimized into DotProducts here
9331                                         l = DotProduct(right, center);
9332                                         for (i = 0;i < 4;i++)
9333                                         {
9334                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9335                                                 f = DotProduct(right, v1) - l;
9336                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9337                                         }
9338                                 }
9339                                 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);
9340                                 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);
9341                         }
9342                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9343                         rsurface.vertex3f_bufferobject = 0;
9344                         rsurface.vertex3f_bufferoffset = 0;
9345                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9346                         rsurface.svector3f_bufferobject = 0;
9347                         rsurface.svector3f_bufferoffset = 0;
9348                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9349                         rsurface.tvector3f_bufferobject = 0;
9350                         rsurface.tvector3f_bufferoffset = 0;
9351                         rsurface.normal3f = rsurface.array_deformednormal3f;
9352                         rsurface.normal3f_bufferobject = 0;
9353                         rsurface.normal3f_bufferoffset = 0;
9354                         break;
9355                 case Q3DEFORM_NORMAL:
9356                         // deform the normals to make reflections wavey
9357                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9358                         {
9359                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9360                                 for (j = 0;j < surface->num_vertices;j++)
9361                                 {
9362                                         float vertex[3];
9363                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9364                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9365                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9366                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9367                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9368                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9369                                         VectorNormalize(normal);
9370                                 }
9371                                 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);
9372                         }
9373                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9374                         rsurface.svector3f_bufferobject = 0;
9375                         rsurface.svector3f_bufferoffset = 0;
9376                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9377                         rsurface.tvector3f_bufferobject = 0;
9378                         rsurface.tvector3f_bufferoffset = 0;
9379                         rsurface.normal3f = rsurface.array_deformednormal3f;
9380                         rsurface.normal3f_bufferobject = 0;
9381                         rsurface.normal3f_bufferoffset = 0;
9382                         break;
9383                 case Q3DEFORM_WAVE:
9384                         // deform vertex array to make wavey water and flags and such
9385                         waveparms[0] = deform->waveparms[0];
9386                         waveparms[1] = deform->waveparms[1];
9387                         waveparms[2] = deform->waveparms[2];
9388                         waveparms[3] = deform->waveparms[3];
9389                         // this is how a divisor of vertex influence on deformation
9390                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9391                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9392                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9393                         {
9394                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9395                                 for (j = 0;j < surface->num_vertices;j++)
9396                                 {
9397                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9398                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9399                                         // if the wavefunc depends on time, evaluate it per-vertex
9400                                         if (waveparms[3])
9401                                         {
9402                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9403                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9404                                         }
9405                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9406                                 }
9407                         }
9408                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9409                         rsurface.vertex3f_bufferobject = 0;
9410                         rsurface.vertex3f_bufferoffset = 0;
9411                         break;
9412                 case Q3DEFORM_BULGE:
9413                         // deform vertex array to make the surface have moving bulges
9414                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9415                         {
9416                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9417                                 for (j = 0;j < surface->num_vertices;j++)
9418                                 {
9419                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9420                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9421                                 }
9422                         }
9423                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9424                         rsurface.vertex3f_bufferobject = 0;
9425                         rsurface.vertex3f_bufferoffset = 0;
9426                         break;
9427                 case Q3DEFORM_MOVE:
9428                         // deform vertex array
9429                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9430                         VectorScale(deform->parms, scale, waveparms);
9431                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9432                         {
9433                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9434                                 for (j = 0;j < surface->num_vertices;j++)
9435                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9436                         }
9437                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9438                         rsurface.vertex3f_bufferobject = 0;
9439                         rsurface.vertex3f_bufferoffset = 0;
9440                         break;
9441                 }
9442         }
9443         // generate texcoords based on the chosen texcoord source
9444         switch(rsurface.texture->tcgen.tcgen)
9445         {
9446         default:
9447         case Q3TCGEN_TEXTURE:
9448                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9449                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9450                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9451                 break;
9452         case Q3TCGEN_LIGHTMAP:
9453                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9454                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9455                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9456                 break;
9457         case Q3TCGEN_VECTOR:
9458                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9459                 {
9460                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9461                         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)
9462                         {
9463                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9464                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9465                         }
9466                 }
9467                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9468                 rsurface.texcoordtexture2f_bufferobject  = 0;
9469                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9470                 break;
9471         case Q3TCGEN_ENVIRONMENT:
9472                 // make environment reflections using a spheremap
9473                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9474                 {
9475                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9476                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9477                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9478                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9479                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9480                         {
9481                                 // identical to Q3A's method, but executed in worldspace so
9482                                 // carried models can be shiny too
9483
9484                                 float viewer[3], d, reflected[3], worldreflected[3];
9485
9486                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9487                                 // VectorNormalize(viewer);
9488
9489                                 d = DotProduct(normal, viewer);
9490
9491                                 reflected[0] = normal[0]*2*d - viewer[0];
9492                                 reflected[1] = normal[1]*2*d - viewer[1];
9493                                 reflected[2] = normal[2]*2*d - viewer[2];
9494                                 // note: this is proportinal to viewer, so we can normalize later
9495
9496                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9497                                 VectorNormalize(worldreflected);
9498
9499                                 // note: this sphere map only uses world x and z!
9500                                 // so positive and negative y will LOOK THE SAME.
9501                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9502                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9503                         }
9504                 }
9505                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9506                 rsurface.texcoordtexture2f_bufferobject  = 0;
9507                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9508                 break;
9509         }
9510         // the only tcmod that needs software vertex processing is turbulent, so
9511         // check for it here and apply the changes if needed
9512         // and we only support that as the first one
9513         // (handling a mixture of turbulent and other tcmods would be problematic
9514         //  without punting it entirely to a software path)
9515         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9516         {
9517                 amplitude = rsurface.texture->tcmods[0].parms[1];
9518                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9519                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9520                 {
9521                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9522                         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)
9523                         {
9524                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9525                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9526                         }
9527                 }
9528                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9529                 rsurface.texcoordtexture2f_bufferobject  = 0;
9530                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9531         }
9532         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9533         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9534         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9535         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9536 }
9537
9538 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9539 {
9540         int i, j;
9541         const msurface_t *surface = texturesurfacelist[0];
9542         const msurface_t *surface2;
9543         int firstvertex;
9544         int endvertex;
9545         int numvertices;
9546         int numtriangles;
9547         // TODO: lock all array ranges before render, rather than on each surface
9548         if (texturenumsurfaces == 1)
9549         {
9550                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9551                 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);
9552         }
9553         else if (r_batchmode.integer == 2)
9554         {
9555                 #define MAXBATCHTRIANGLES 4096
9556                 int batchtriangles = 0;
9557                 static int batchelements[MAXBATCHTRIANGLES*3];
9558                 for (i = 0;i < texturenumsurfaces;i = j)
9559                 {
9560                         surface = texturesurfacelist[i];
9561                         j = i + 1;
9562                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9563                         {
9564                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9565                                 continue;
9566                         }
9567                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9568                         batchtriangles = surface->num_triangles;
9569                         firstvertex = surface->num_firstvertex;
9570                         endvertex = surface->num_firstvertex + surface->num_vertices;
9571                         for (;j < texturenumsurfaces;j++)
9572                         {
9573                                 surface2 = texturesurfacelist[j];
9574                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9575                                         break;
9576                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9577                                 batchtriangles += surface2->num_triangles;
9578                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9579                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9580                         }
9581                         surface2 = texturesurfacelist[j-1];
9582                         numvertices = endvertex - firstvertex;
9583                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9584                 }
9585         }
9586         else if (r_batchmode.integer == 1)
9587         {
9588                 for (i = 0;i < texturenumsurfaces;i = j)
9589                 {
9590                         surface = texturesurfacelist[i];
9591                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9592                                 if (texturesurfacelist[j] != surface2)
9593                                         break;
9594                         surface2 = texturesurfacelist[j-1];
9595                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9596                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9597                         GL_LockArrays(surface->num_firstvertex, numvertices);
9598                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9599                 }
9600         }
9601         else
9602         {
9603                 for (i = 0;i < texturenumsurfaces;i++)
9604                 {
9605                         surface = texturesurfacelist[i];
9606                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9607                         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);
9608                 }
9609         }
9610 }
9611
9612 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9613 {
9614         switch(vid.renderpath)
9615         {
9616         case RENDERPATH_CGGL:
9617 #ifdef SUPPORTCG
9618                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9619                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9620 #endif
9621                 break;
9622         case RENDERPATH_GL20:
9623                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9624                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9625                 break;
9626         case RENDERPATH_GL13:
9627         case RENDERPATH_GL11:
9628                 R_Mesh_TexBind(0, surface->lightmaptexture);
9629                 break;
9630         }
9631 }
9632
9633 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9634 {
9635         // pick the closest matching water plane and bind textures
9636         int planeindex, vertexindex;
9637         float d, bestd;
9638         vec3_t vert;
9639         const float *v;
9640         r_waterstate_waterplane_t *p, *bestp;
9641         bestd = 0;
9642         bestp = NULL;
9643         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9644         {
9645                 d = 0;
9646                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9647                 {
9648                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9649                         d += fabs(PlaneDiff(vert, &p->plane));
9650                 }
9651                 if (bestd > d || !bestp)
9652                 {
9653                         bestd = d;
9654                         bestp = p;
9655                 }
9656         }
9657         switch(vid.renderpath)
9658         {
9659         case RENDERPATH_CGGL:
9660 #ifdef SUPPORTCG
9661                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9662                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9663 #endif
9664                 break;
9665         case RENDERPATH_GL20:
9666                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9667                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9668                 break;
9669         case RENDERPATH_GL13:
9670         case RENDERPATH_GL11:
9671                 break;
9672         }
9673 }
9674
9675 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9676 {
9677         int i;
9678         const msurface_t *surface;
9679         if (r_waterstate.renderingscene)
9680                 return;
9681         for (i = 0;i < texturenumsurfaces;i++)
9682         {
9683                 surface = texturesurfacelist[i];
9684                 RSurf_BindLightmapForSurface(surface);
9685                 RSurf_BindReflectionForSurface(surface);
9686                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9687                 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);
9688         }
9689 }
9690
9691 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9692 {
9693         int i;
9694         int j;
9695         const msurface_t *surface = texturesurfacelist[0];
9696         const msurface_t *surface2;
9697         int firstvertex;
9698         int endvertex;
9699         int numvertices;
9700         int numtriangles;
9701         if (texturenumsurfaces == 1)
9702         {
9703                 RSurf_BindLightmapForSurface(surface);
9704                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9705                 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);
9706         }
9707         else if (r_batchmode.integer == 2)
9708         {
9709 #define MAXBATCHTRIANGLES 4096
9710                 int batchtriangles = 0;
9711                 static int batchelements[MAXBATCHTRIANGLES*3];
9712                 for (i = 0;i < texturenumsurfaces;i = j)
9713                 {
9714                         surface = texturesurfacelist[i];
9715                         RSurf_BindLightmapForSurface(surface);
9716                         j = i + 1;
9717                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9718                         {
9719                                 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);
9720                                 continue;
9721                         }
9722                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9723                         batchtriangles = surface->num_triangles;
9724                         firstvertex = surface->num_firstvertex;
9725                         endvertex = surface->num_firstvertex + surface->num_vertices;
9726                         for (;j < texturenumsurfaces;j++)
9727                         {
9728                                 surface2 = texturesurfacelist[j];
9729                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9730                                         break;
9731                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9732                                 batchtriangles += surface2->num_triangles;
9733                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9734                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9735                         }
9736                         surface2 = texturesurfacelist[j-1];
9737                         numvertices = endvertex - firstvertex;
9738                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9739                 }
9740         }
9741         else if (r_batchmode.integer == 1)
9742         {
9743 #if 0
9744                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9745                 for (i = 0;i < texturenumsurfaces;i = j)
9746                 {
9747                         surface = texturesurfacelist[i];
9748                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9749                                 if (texturesurfacelist[j] != surface2)
9750                                         break;
9751                         Con_Printf(" %i", j - i);
9752                 }
9753                 Con_Printf("\n");
9754                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9755 #endif
9756                 for (i = 0;i < texturenumsurfaces;i = j)
9757                 {
9758                         surface = texturesurfacelist[i];
9759                         RSurf_BindLightmapForSurface(surface);
9760                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9761                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9762                                         break;
9763 #if 0
9764                         Con_Printf(" %i", j - i);
9765 #endif
9766                         surface2 = texturesurfacelist[j-1];
9767                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9768                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9769                         GL_LockArrays(surface->num_firstvertex, numvertices);
9770                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9771                 }
9772 #if 0
9773                 Con_Printf("\n");
9774 #endif
9775         }
9776         else
9777         {
9778                 for (i = 0;i < texturenumsurfaces;i++)
9779                 {
9780                         surface = texturesurfacelist[i];
9781                         RSurf_BindLightmapForSurface(surface);
9782                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9783                         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);
9784                 }
9785         }
9786 }
9787
9788 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9789 {
9790         int j;
9791         int texturesurfaceindex;
9792         if (r_showsurfaces.integer == 2)
9793         {
9794                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9795                 {
9796                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9797                         for (j = 0;j < surface->num_triangles;j++)
9798                         {
9799                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9800                                 GL_Color(f, f, f, 1);
9801                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9802                         }
9803                 }
9804         }
9805         else
9806         {
9807                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9808                 {
9809                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9810                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9811                         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);
9812                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9813                         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);
9814                 }
9815         }
9816 }
9817
9818 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9819 {
9820         int texturesurfaceindex;
9821         int i;
9822         const float *v;
9823         float *c2;
9824         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9825         {
9826                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9827                 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)
9828                 {
9829                         c2[0] = 0.5;
9830                         c2[1] = 0.5;
9831                         c2[2] = 0.5;
9832                         c2[3] = 1;
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_ApplyFog(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         {
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;
9858                                 c2[1] = c[1] * f;
9859                                 c2[2] = c[2] * f;
9860                                 c2[3] = c[3];
9861                         }
9862                 }
9863         }
9864         else
9865         {
9866                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9867                 {
9868                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9869                         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)
9870                         {
9871                                 f = RSurf_FogVertex(v);
9872                                 c2[0] = f;
9873                                 c2[1] = f;
9874                                 c2[2] = f;
9875                                 c2[3] = 1;
9876                         }
9877                 }
9878         }
9879         rsurface.lightmapcolor4f = rsurface.array_color4f;
9880         rsurface.lightmapcolor4f_bufferobject = 0;
9881         rsurface.lightmapcolor4f_bufferoffset = 0;
9882 }
9883
9884 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9885 {
9886         int texturesurfaceindex;
9887         int i;
9888         float f;
9889         const float *v;
9890         const float *c;
9891         float *c2;
9892         if (!rsurface.lightmapcolor4f)
9893                 return;
9894         // generate color arrays for the surfaces in this list
9895         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9896         {
9897                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9898                 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)
9899                 {
9900                         f = RSurf_FogVertex(v);
9901                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9902                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9903                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9904                         c2[3] = c[3];
9905                 }
9906         }
9907         rsurface.lightmapcolor4f = rsurface.array_color4f;
9908         rsurface.lightmapcolor4f_bufferobject = 0;
9909         rsurface.lightmapcolor4f_bufferoffset = 0;
9910 }
9911
9912 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
9913 {
9914         int texturesurfaceindex;
9915         int i;
9916         const float *c;
9917         float *c2;
9918         if (!rsurface.lightmapcolor4f)
9919                 return;
9920         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9921         {
9922                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9923                 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)
9924                 {
9925                         c2[0] = c[0] * r;
9926                         c2[1] = c[1] * g;
9927                         c2[2] = c[2] * b;
9928                         c2[3] = c[3] * a;
9929                 }
9930         }
9931         rsurface.lightmapcolor4f = rsurface.array_color4f;
9932         rsurface.lightmapcolor4f_bufferobject = 0;
9933         rsurface.lightmapcolor4f_bufferoffset = 0;
9934 }
9935
9936 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9937 {
9938         int texturesurfaceindex;
9939         int i;
9940         const float *c;
9941         float *c2;
9942         if (!rsurface.lightmapcolor4f)
9943                 return;
9944         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9945         {
9946                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9947                 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)
9948                 {
9949                         c2[0] = c[0] + r_refdef.scene.ambient;
9950                         c2[1] = c[1] + r_refdef.scene.ambient;
9951                         c2[2] = c[2] + r_refdef.scene.ambient;
9952                         c2[3] = c[3];
9953                 }
9954         }
9955         rsurface.lightmapcolor4f = rsurface.array_color4f;
9956         rsurface.lightmapcolor4f_bufferobject = 0;
9957         rsurface.lightmapcolor4f_bufferoffset = 0;
9958 }
9959
9960 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9961 {
9962         // TODO: optimize
9963         rsurface.lightmapcolor4f = NULL;
9964         rsurface.lightmapcolor4f_bufferobject = 0;
9965         rsurface.lightmapcolor4f_bufferoffset = 0;
9966         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9967         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9968         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9969         GL_Color(r, g, b, a);
9970         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
9971 }
9972
9973 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9974 {
9975         // TODO: optimize applyfog && applycolor case
9976         // just apply fog if necessary, and tint the fog color array if necessary
9977         rsurface.lightmapcolor4f = NULL;
9978         rsurface.lightmapcolor4f_bufferobject = 0;
9979         rsurface.lightmapcolor4f_bufferoffset = 0;
9980         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9981         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9982         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9983         GL_Color(r, g, b, a);
9984         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9985 }
9986
9987 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9988 {
9989         int texturesurfaceindex;
9990         int i;
9991         float *c;
9992         // TODO: optimize
9993         if (texturesurfacelist[0]->lightmapinfo)
9994         {
9995                 // generate color arrays for the surfaces in this list
9996                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9997                 {
9998                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9999                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10000                         {
10001                                 if (surface->lightmapinfo->samples)
10002                                 {
10003                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10004                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10005                                         VectorScale(lm, scale, c);
10006                                         if (surface->lightmapinfo->styles[1] != 255)
10007                                         {
10008                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10009                                                 lm += size3;
10010                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10011                                                 VectorMA(c, scale, lm, c);
10012                                                 if (surface->lightmapinfo->styles[2] != 255)
10013                                                 {
10014                                                         lm += size3;
10015                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10016                                                         VectorMA(c, scale, lm, c);
10017                                                         if (surface->lightmapinfo->styles[3] != 255)
10018                                                         {
10019                                                                 lm += size3;
10020                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10021                                                                 VectorMA(c, scale, lm, c);
10022                                                         }
10023                                                 }
10024                                         }
10025                                 }
10026                                 else
10027                                         VectorClear(c);
10028                                 c[3] = 1;
10029                         }
10030                 }
10031                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10032                 rsurface.lightmapcolor4f_bufferobject = 0;
10033                 rsurface.lightmapcolor4f_bufferoffset = 0;
10034         }
10035         else
10036         {
10037                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10038                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10039                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10040         }
10041         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10042         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10043         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10044         GL_Color(r, g, b, a);
10045         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10046 }
10047
10048 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10049 {
10050         int texturesurfaceindex;
10051         int i;
10052         float f;
10053         float alpha;
10054         const float *v;
10055         const float *n;
10056         float *c;
10057         vec3_t ambientcolor;
10058         vec3_t diffusecolor;
10059         vec3_t lightdir;
10060         // TODO: optimize
10061         // model lighting
10062         VectorCopy(rsurface.modellight_lightdir, lightdir);
10063         f = 0.5f * r_refdef.lightmapintensity;
10064         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10065         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10066         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10067         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10068         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10069         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10070         alpha = *a;
10071         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10072         {
10073                 // generate color arrays for the surfaces in this list
10074                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10075                 {
10076                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10077                         int numverts = surface->num_vertices;
10078                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10079                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10080                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10081                         // q3-style directional shading
10082                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10083                         {
10084                                 if ((f = DotProduct(n, lightdir)) > 0)
10085                                         VectorMA(ambientcolor, f, diffusecolor, c);
10086                                 else
10087                                         VectorCopy(ambientcolor, c);
10088                                 c[3] = alpha;
10089                         }
10090                 }
10091                 *r = 1;
10092                 *g = 1;
10093                 *b = 1;
10094                 *a = 1;
10095                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10096                 rsurface.lightmapcolor4f_bufferobject = 0;
10097                 rsurface.lightmapcolor4f_bufferoffset = 0;
10098                 *applycolor = false;
10099         }
10100         else
10101         {
10102                 *r = ambientcolor[0];
10103                 *g = ambientcolor[1];
10104                 *b = ambientcolor[2];
10105                 rsurface.lightmapcolor4f = NULL;
10106                 rsurface.lightmapcolor4f_bufferobject = 0;
10107                 rsurface.lightmapcolor4f_bufferoffset = 0;
10108         }
10109 }
10110
10111 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10112 {
10113         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10114         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10115         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10116         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10117         GL_Color(r, g, b, a);
10118         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10119 }
10120
10121 void RSurf_SetupDepthAndCulling(void)
10122 {
10123         // submodels are biased to avoid z-fighting with world surfaces that they
10124         // may be exactly overlapping (avoids z-fighting artifacts on certain
10125         // doors and things in Quake maps)
10126         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10127         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10128         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10129         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10130 }
10131
10132 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10133 {
10134         // transparent sky would be ridiculous
10135         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10136                 return;
10137         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10138         skyrenderlater = true;
10139         RSurf_SetupDepthAndCulling();
10140         GL_DepthMask(true);
10141         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10142         // skymasking on them, and Quake3 never did sky masking (unlike
10143         // software Quake and software Quake2), so disable the sky masking
10144         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10145         // and skymasking also looks very bad when noclipping outside the
10146         // level, so don't use it then either.
10147         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10148         {
10149                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10150                 R_Mesh_ColorPointer(NULL, 0, 0);
10151                 R_Mesh_ResetTextureState();
10152                 if (skyrendermasked)
10153                 {
10154                         R_SetupShader_DepthOrShadow();
10155                         // depth-only (masking)
10156                         GL_ColorMask(0,0,0,0);
10157                         // just to make sure that braindead drivers don't draw
10158                         // anything despite that colormask...
10159                         GL_BlendFunc(GL_ZERO, GL_ONE);
10160                 }
10161                 else
10162                 {
10163                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10164                         // fog sky
10165                         GL_BlendFunc(GL_ONE, GL_ZERO);
10166                 }
10167                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10168                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10169                 if (skyrendermasked)
10170                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10171         }
10172         R_Mesh_ResetTextureState();
10173         GL_Color(1, 1, 1, 1);
10174 }
10175
10176 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10177 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10178 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10179 {
10180         qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
10181         qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
10182
10183         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10184                 return;
10185
10186         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10187                 R_Mesh_ColorPointer(NULL, 0, 0);
10188         else
10189                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10190
10191         if (refract)
10192         {
10193                 // render background
10194                 GL_BlendFunc(GL_ONE, GL_ZERO);
10195                 GL_DepthMask(true);
10196                 GL_AlphaTest(false);
10197
10198                 GL_Color(1, 1, 1, 1);
10199                 R_Mesh_ColorPointer(NULL, 0, 0);
10200
10201                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10202                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10203                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10204                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10205                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10206                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10207                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10208                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10209                 GL_LockArrays(0, 0);
10210
10211                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10212                 GL_DepthMask(false);
10213                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10214                         R_Mesh_ColorPointer(NULL, 0, 0);
10215                 else
10216                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10217         }
10218
10219         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10220
10221         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10222         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10223         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10224         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10225         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10226         if (!prepass)
10227                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10228
10229         if (refract)
10230                 GL_DepthMask(true);
10231         else
10232                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10233         GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10234         GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
10235
10236         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10237         {
10238                 if (refract || reflect)
10239                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10240                 else
10241                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10242         }
10243         else
10244         {
10245                 if (refract || reflect)
10246                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10247                 else
10248                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10249         }
10250         GL_LockArrays(0, 0);
10251 }
10252
10253 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10254 {
10255         // OpenGL 1.3 path - anything not completely ancient
10256         int texturesurfaceindex;
10257         qboolean applycolor;
10258         qboolean applyfog;
10259         int layerindex;
10260         const texturelayer_t *layer;
10261         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10262
10263         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10264         {
10265                 vec4_t layercolor;
10266                 int layertexrgbscale;
10267                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10268                 {
10269                         if (layerindex == 0)
10270                                 GL_AlphaTest(true);
10271                         else
10272                         {
10273                                 GL_AlphaTest(false);
10274                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10275                         }
10276                 }
10277                 GL_DepthMask(layer->depthmask && writedepth);
10278                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10279                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10280                 {
10281                         layertexrgbscale = 4;
10282                         VectorScale(layer->color, 0.25f, layercolor);
10283                 }
10284                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10285                 {
10286                         layertexrgbscale = 2;
10287                         VectorScale(layer->color, 0.5f, layercolor);
10288                 }
10289                 else
10290                 {
10291                         layertexrgbscale = 1;
10292                         VectorScale(layer->color, 1.0f, layercolor);
10293                 }
10294                 layercolor[3] = layer->color[3];
10295                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10296                 R_Mesh_ColorPointer(NULL, 0, 0);
10297                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10298                 switch (layer->type)
10299                 {
10300                 case TEXTURELAYERTYPE_LITTEXTURE:
10301                         // single-pass lightmapped texture with 2x rgbscale
10302                         R_Mesh_TexBind(0, r_texture_white);
10303                         R_Mesh_TexMatrix(0, NULL);
10304                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10305                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10306                         R_Mesh_TexBind(1, layer->texture);
10307                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10308                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10309                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10310                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10311                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10312                         else if (rsurface.uselightmaptexture)
10313                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10314                         else
10315                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10316                         break;
10317                 case TEXTURELAYERTYPE_TEXTURE:
10318                         // singletexture unlit texture with transparency support
10319                         R_Mesh_TexBind(0, layer->texture);
10320                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10321                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10322                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10323                         R_Mesh_TexBind(1, 0);
10324                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10325                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10326                         break;
10327                 case TEXTURELAYERTYPE_FOG:
10328                         // singletexture fogging
10329                         if (layer->texture)
10330                         {
10331                                 R_Mesh_TexBind(0, layer->texture);
10332                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10333                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10334                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10335                         }
10336                         else
10337                         {
10338                                 R_Mesh_TexBind(0, 0);
10339                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10340                         }
10341                         R_Mesh_TexBind(1, 0);
10342                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10343                         // generate a color array for the fog pass
10344                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10345                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10346                         {
10347                                 int i;
10348                                 float f;
10349                                 const float *v;
10350                                 float *c;
10351                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10352                                 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)
10353                                 {
10354                                         f = 1 - RSurf_FogVertex(v);
10355                                         c[0] = layercolor[0];
10356                                         c[1] = layercolor[1];
10357                                         c[2] = layercolor[2];
10358                                         c[3] = f * layercolor[3];
10359                                 }
10360                         }
10361                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10362                         break;
10363                 default:
10364                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10365                 }
10366                 GL_LockArrays(0, 0);
10367         }
10368         CHECKGLERROR
10369         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10370         {
10371                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10372                 GL_AlphaTest(false);
10373         }
10374 }
10375
10376 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10377 {
10378         // OpenGL 1.1 - crusty old voodoo path
10379         int texturesurfaceindex;
10380         qboolean applyfog;
10381         int layerindex;
10382         const texturelayer_t *layer;
10383         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10384
10385         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10386         {
10387                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10388                 {
10389                         if (layerindex == 0)
10390                                 GL_AlphaTest(true);
10391                         else
10392                         {
10393                                 GL_AlphaTest(false);
10394                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10395                         }
10396                 }
10397                 GL_DepthMask(layer->depthmask && writedepth);
10398                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10399                 R_Mesh_ColorPointer(NULL, 0, 0);
10400                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10401                 switch (layer->type)
10402                 {
10403                 case TEXTURELAYERTYPE_LITTEXTURE:
10404                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10405                         {
10406                                 // two-pass lit texture with 2x rgbscale
10407                                 // first the lightmap pass
10408                                 R_Mesh_TexBind(0, r_texture_white);
10409                                 R_Mesh_TexMatrix(0, NULL);
10410                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10411                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10412                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10413                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10414                                 else if (rsurface.uselightmaptexture)
10415                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10416                                 else
10417                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10418                                 GL_LockArrays(0, 0);
10419                                 // then apply the texture to it
10420                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10421                                 R_Mesh_TexBind(0, layer->texture);
10422                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10423                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10424                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10425                                 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);
10426                         }
10427                         else
10428                         {
10429                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10430                                 R_Mesh_TexBind(0, layer->texture);
10431                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10432                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10433                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10434                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10435                                         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);
10436                                 else
10437                                         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);
10438                         }
10439                         break;
10440                 case TEXTURELAYERTYPE_TEXTURE:
10441                         // singletexture unlit texture with transparency support
10442                         R_Mesh_TexBind(0, layer->texture);
10443                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10444                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10445                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10446                         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);
10447                         break;
10448                 case TEXTURELAYERTYPE_FOG:
10449                         // singletexture fogging
10450                         if (layer->texture)
10451                         {
10452                                 R_Mesh_TexBind(0, layer->texture);
10453                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10454                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10455                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10456                         }
10457                         else
10458                         {
10459                                 R_Mesh_TexBind(0, 0);
10460                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10461                         }
10462                         // generate a color array for the fog pass
10463                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10464                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10465                         {
10466                                 int i;
10467                                 float f;
10468                                 const float *v;
10469                                 float *c;
10470                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10471                                 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)
10472                                 {
10473                                         f = 1 - RSurf_FogVertex(v);
10474                                         c[0] = layer->color[0];
10475                                         c[1] = layer->color[1];
10476                                         c[2] = layer->color[2];
10477                                         c[3] = f * layer->color[3];
10478                                 }
10479                         }
10480                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10481                         break;
10482                 default:
10483                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10484                 }
10485                 GL_LockArrays(0, 0);
10486         }
10487         CHECKGLERROR
10488         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10489         {
10490                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10491                 GL_AlphaTest(false);
10492         }
10493 }
10494
10495 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10496 {
10497         float c[4];
10498
10499         GL_AlphaTest(false);
10500         R_Mesh_ColorPointer(NULL, 0, 0);
10501         R_Mesh_ResetTextureState();
10502         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10503
10504         if(rsurface.texture && rsurface.texture->currentskinframe)
10505         {
10506                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10507                 c[3] *= rsurface.texture->currentalpha;
10508         }
10509         else
10510         {
10511                 c[0] = 1;
10512                 c[1] = 0;
10513                 c[2] = 1;
10514                 c[3] = 1;
10515         }
10516
10517         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10518         {
10519                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10520                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10521                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10522         }
10523
10524         // brighten it up (as texture value 127 means "unlit")
10525         c[0] *= 2 * r_refdef.view.colorscale;
10526         c[1] *= 2 * r_refdef.view.colorscale;
10527         c[2] *= 2 * r_refdef.view.colorscale;
10528
10529         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10530                 c[3] *= r_wateralpha.value;
10531
10532         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10533         {
10534                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10535                 GL_DepthMask(false);
10536         }
10537         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10538         {
10539                 GL_BlendFunc(GL_ONE, GL_ONE);
10540                 GL_DepthMask(false);
10541         }
10542         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10543         {
10544                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10545                 GL_DepthMask(false);
10546         }
10547         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10548         {
10549                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10550                 GL_DepthMask(false);
10551         }
10552         else
10553         {
10554                 GL_BlendFunc(GL_ONE, GL_ZERO);
10555                 GL_DepthMask(writedepth);
10556         }
10557
10558         rsurface.lightmapcolor4f = NULL;
10559
10560         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10561         {
10562                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10563
10564                 rsurface.lightmapcolor4f = NULL;
10565                 rsurface.lightmapcolor4f_bufferobject = 0;
10566                 rsurface.lightmapcolor4f_bufferoffset = 0;
10567         }
10568         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10569         {
10570                 qboolean applycolor = true;
10571                 float one = 1.0;
10572
10573                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10574
10575                 r_refdef.lightmapintensity = 1;
10576                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10577                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10578         }
10579         else
10580         {
10581                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10582
10583                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10584                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10585                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10586         }
10587
10588         if(!rsurface.lightmapcolor4f)
10589                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10590
10591         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10592         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10593         if(r_refdef.fogenabled)
10594                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10595
10596         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10597         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10598 }
10599
10600 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10601 {
10602         CHECKGLERROR
10603         RSurf_SetupDepthAndCulling();
10604         if (r_showsurfaces.integer == 3 && !prepass)
10605         {
10606                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10607                 return;
10608         }
10609         switch (vid.renderpath)
10610         {
10611         case RENDERPATH_GL20:
10612         case RENDERPATH_CGGL:
10613                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10614                 break;
10615         case RENDERPATH_GL13:
10616                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10617                 break;
10618         case RENDERPATH_GL11:
10619                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10620                 break;
10621         }
10622         CHECKGLERROR
10623 }
10624
10625 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10626 {
10627         CHECKGLERROR
10628         RSurf_SetupDepthAndCulling();
10629         if (r_showsurfaces.integer == 3 && !prepass)
10630         {
10631                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10632                 return;
10633         }
10634         switch (vid.renderpath)
10635         {
10636         case RENDERPATH_GL20:
10637         case RENDERPATH_CGGL:
10638                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10639                 break;
10640         case RENDERPATH_GL13:
10641                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10642                 break;
10643         case RENDERPATH_GL11:
10644                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10645                 break;
10646         }
10647         CHECKGLERROR
10648 }
10649
10650 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10651 {
10652         int i, j;
10653         int texturenumsurfaces, endsurface;
10654         texture_t *texture;
10655         const msurface_t *surface;
10656         const msurface_t *texturesurfacelist[256];
10657
10658         // if the model is static it doesn't matter what value we give for
10659         // wantnormals and wanttangents, so this logic uses only rules applicable
10660         // to a model, knowing that they are meaningless otherwise
10661         if (ent == r_refdef.scene.worldentity)
10662                 RSurf_ActiveWorldEntity();
10663         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10664                 RSurf_ActiveModelEntity(ent, false, false, false);
10665         else
10666         {
10667                 switch (vid.renderpath)
10668                 {
10669                 case RENDERPATH_GL20:
10670                 case RENDERPATH_CGGL:
10671                         RSurf_ActiveModelEntity(ent, true, true, false);
10672                         break;
10673                 case RENDERPATH_GL13:
10674                 case RENDERPATH_GL11:
10675                         RSurf_ActiveModelEntity(ent, true, false, false);
10676                         break;
10677                 }
10678         }
10679
10680         if (r_transparentdepthmasking.integer)
10681         {
10682                 qboolean setup = false;
10683                 for (i = 0;i < numsurfaces;i = j)
10684                 {
10685                         j = i + 1;
10686                         surface = rsurface.modelsurfaces + surfacelist[i];
10687                         texture = surface->texture;
10688                         rsurface.texture = R_GetCurrentTexture(texture);
10689                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10690                         // scan ahead until we find a different texture
10691                         endsurface = min(i + 1024, numsurfaces);
10692                         texturenumsurfaces = 0;
10693                         texturesurfacelist[texturenumsurfaces++] = surface;
10694                         for (;j < endsurface;j++)
10695                         {
10696                                 surface = rsurface.modelsurfaces + surfacelist[j];
10697                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10698                                         break;
10699                                 texturesurfacelist[texturenumsurfaces++] = surface;
10700                         }
10701                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10702                                 continue;
10703                         // render the range of surfaces as depth
10704                         if (!setup)
10705                         {
10706                                 setup = true;
10707                                 GL_ColorMask(0,0,0,0);
10708                                 GL_Color(1,1,1,1);
10709                                 GL_DepthTest(true);
10710                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10711                                 GL_DepthMask(true);
10712                                 GL_AlphaTest(false);
10713                                 R_Mesh_ColorPointer(NULL, 0, 0);
10714                                 R_Mesh_ResetTextureState();
10715                                 R_SetupShader_DepthOrShadow();
10716                         }
10717                         RSurf_SetupDepthAndCulling();
10718                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10719                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10720                 }
10721                 if (setup)
10722                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10723         }
10724
10725         for (i = 0;i < numsurfaces;i = j)
10726         {
10727                 j = i + 1;
10728                 surface = rsurface.modelsurfaces + surfacelist[i];
10729                 texture = surface->texture;
10730                 rsurface.texture = R_GetCurrentTexture(texture);
10731                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10732                 // scan ahead until we find a different texture
10733                 endsurface = min(i + 1024, numsurfaces);
10734                 texturenumsurfaces = 0;
10735                 texturesurfacelist[texturenumsurfaces++] = surface;
10736                 for (;j < endsurface;j++)
10737                 {
10738                         surface = rsurface.modelsurfaces + surfacelist[j];
10739                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10740                                 break;
10741                         texturesurfacelist[texturenumsurfaces++] = surface;
10742                 }
10743                 // render the range of surfaces
10744                 if (ent == r_refdef.scene.worldentity)
10745                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10746                 else
10747                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10748         }
10749         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10750         GL_AlphaTest(false);
10751 }
10752
10753 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10754 {
10755         // transparent surfaces get pushed off into the transparent queue
10756         int surfacelistindex;
10757         const msurface_t *surface;
10758         vec3_t tempcenter, center;
10759         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10760         {
10761                 surface = texturesurfacelist[surfacelistindex];
10762                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10763                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10764                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10765                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10766                 if (queueentity->transparent_offset) // transparent offset
10767                 {
10768                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10769                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10770                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10771                 }
10772                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10773         }
10774 }
10775
10776 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10777 {
10778         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10779         CHECKGLERROR
10780         if (depthonly)
10781         {
10782                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10783                         return;
10784                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10785                         return;
10786                 RSurf_SetupDepthAndCulling();
10787                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10788                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10789         }
10790         else if (prepass)
10791         {
10792                 if (!rsurface.texture->currentnumlayers)
10793                         return;
10794                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10795                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10796                 else
10797                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10798         }
10799         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10800         {
10801                 RSurf_SetupDepthAndCulling();
10802                 GL_AlphaTest(false);
10803                 R_Mesh_ColorPointer(NULL, 0, 0);
10804                 R_Mesh_ResetTextureState();
10805                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10806                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10807                 GL_DepthMask(true);
10808                 GL_BlendFunc(GL_ONE, GL_ZERO);
10809                 GL_Color(0, 0, 0, 1);
10810                 GL_DepthTest(writedepth);
10811                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10812         }
10813         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10814         {
10815                 RSurf_SetupDepthAndCulling();
10816                 GL_AlphaTest(false);
10817                 R_Mesh_ColorPointer(NULL, 0, 0);
10818                 R_Mesh_ResetTextureState();
10819                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10820                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10821                 GL_DepthMask(true);
10822                 GL_BlendFunc(GL_ONE, GL_ZERO);
10823                 GL_DepthTest(true);
10824                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10825         }
10826         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10827                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10828         else if (!rsurface.texture->currentnumlayers)
10829                 return;
10830         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10831         {
10832                 // in the deferred case, transparent surfaces were queued during prepass
10833                 if (!r_shadow_usingdeferredprepass)
10834                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10835         }
10836         else
10837         {
10838                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10839                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10840         }
10841         CHECKGLERROR
10842 }
10843
10844 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10845 {
10846         int i, j;
10847         texture_t *texture;
10848         // break the surface list down into batches by texture and use of lightmapping
10849         for (i = 0;i < numsurfaces;i = j)
10850         {
10851                 j = i + 1;
10852                 // texture is the base texture pointer, rsurface.texture is the
10853                 // current frame/skin the texture is directing us to use (for example
10854                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10855                 // use skin 1 instead)
10856                 texture = surfacelist[i]->texture;
10857                 rsurface.texture = R_GetCurrentTexture(texture);
10858                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10859                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10860                 {
10861                         // if this texture is not the kind we want, skip ahead to the next one
10862                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10863                                 ;
10864                         continue;
10865                 }
10866                 // simply scan ahead until we find a different texture or lightmap state
10867                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10868                         ;
10869                 // render the range of surfaces
10870                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10871         }
10872 }
10873
10874 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10875 {
10876         CHECKGLERROR
10877         if (depthonly)
10878         {
10879                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10880                         return;
10881                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10882                         return;
10883                 RSurf_SetupDepthAndCulling();
10884                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10885                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10886         }
10887         else if (prepass)
10888         {
10889                 if (!rsurface.texture->currentnumlayers)
10890                         return;
10891                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10892                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10893                 else
10894                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10895         }
10896         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10897         {
10898                 RSurf_SetupDepthAndCulling();
10899                 GL_AlphaTest(false);
10900                 R_Mesh_ColorPointer(NULL, 0, 0);
10901                 R_Mesh_ResetTextureState();
10902                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10903                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10904                 GL_DepthMask(true);
10905                 GL_BlendFunc(GL_ONE, GL_ZERO);
10906                 GL_Color(0, 0, 0, 1);
10907                 GL_DepthTest(writedepth);
10908                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10909         }
10910         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10911         {
10912                 RSurf_SetupDepthAndCulling();
10913                 GL_AlphaTest(false);
10914                 R_Mesh_ColorPointer(NULL, 0, 0);
10915                 R_Mesh_ResetTextureState();
10916                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10917                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10918                 GL_DepthMask(true);
10919                 GL_BlendFunc(GL_ONE, GL_ZERO);
10920                 GL_DepthTest(true);
10921                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10922         }
10923         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10924                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10925         else if (!rsurface.texture->currentnumlayers)
10926                 return;
10927         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10928         {
10929                 // in the deferred case, transparent surfaces were queued during prepass
10930                 if (!r_shadow_usingdeferredprepass)
10931                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10932         }
10933         else
10934         {
10935                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10936                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10937         }
10938         CHECKGLERROR
10939 }
10940
10941 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10942 {
10943         int i, j;
10944         texture_t *texture;
10945         // break the surface list down into batches by texture and use of lightmapping
10946         for (i = 0;i < numsurfaces;i = j)
10947         {
10948                 j = i + 1;
10949                 // texture is the base texture pointer, rsurface.texture is the
10950                 // current frame/skin the texture is directing us to use (for example
10951                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10952                 // use skin 1 instead)
10953                 texture = surfacelist[i]->texture;
10954                 rsurface.texture = R_GetCurrentTexture(texture);
10955                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10956                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10957                 {
10958                         // if this texture is not the kind we want, skip ahead to the next one
10959                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10960                                 ;
10961                         continue;
10962                 }
10963                 // simply scan ahead until we find a different texture or lightmap state
10964                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10965                         ;
10966                 // render the range of surfaces
10967                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10968         }
10969 }
10970
10971 float locboxvertex3f[6*4*3] =
10972 {
10973         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10974         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10975         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10976         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10977         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10978         1,0,0, 0,0,0, 0,1,0, 1,1,0
10979 };
10980
10981 unsigned short locboxelements[6*2*3] =
10982 {
10983          0, 1, 2, 0, 2, 3,
10984          4, 5, 6, 4, 6, 7,
10985          8, 9,10, 8,10,11,
10986         12,13,14, 12,14,15,
10987         16,17,18, 16,18,19,
10988         20,21,22, 20,22,23
10989 };
10990
10991 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10992 {
10993         int i, j;
10994         cl_locnode_t *loc = (cl_locnode_t *)ent;
10995         vec3_t mins, size;
10996         float vertex3f[6*4*3];
10997         CHECKGLERROR
10998         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10999         GL_DepthMask(false);
11000         GL_DepthRange(0, 1);
11001         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11002         GL_DepthTest(true);
11003         GL_CullFace(GL_NONE);
11004         R_EntityMatrix(&identitymatrix);
11005
11006         R_Mesh_VertexPointer(vertex3f, 0, 0);
11007         R_Mesh_ColorPointer(NULL, 0, 0);
11008         R_Mesh_ResetTextureState();
11009         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11010
11011         i = surfacelist[0];
11012         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11013                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11014                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11015                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11016
11017         if (VectorCompare(loc->mins, loc->maxs))
11018         {
11019                 VectorSet(size, 2, 2, 2);
11020                 VectorMA(loc->mins, -0.5f, size, mins);
11021         }
11022         else
11023         {
11024                 VectorCopy(loc->mins, mins);
11025                 VectorSubtract(loc->maxs, loc->mins, size);
11026         }
11027
11028         for (i = 0;i < 6*4*3;)
11029                 for (j = 0;j < 3;j++, i++)
11030                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11031
11032         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11033 }
11034
11035 void R_DrawLocs(void)
11036 {
11037         int index;
11038         cl_locnode_t *loc, *nearestloc;
11039         vec3_t center;
11040         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11041         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11042         {
11043                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11044                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11045         }
11046 }
11047
11048 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11049 {
11050         if (decalsystem->decals)
11051                 Mem_Free(decalsystem->decals);
11052         memset(decalsystem, 0, sizeof(*decalsystem));
11053 }
11054
11055 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)
11056 {
11057         tridecal_t *decal;
11058         tridecal_t *decals;
11059         int i;
11060         int maxdecals;
11061
11062         // expand or initialize the system
11063         if (decalsystem->maxdecals <= decalsystem->numdecals)
11064         {
11065                 decalsystem_t old = *decalsystem;
11066                 qboolean useshortelements;
11067                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11068                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11069                 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)));
11070                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11071                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11072                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11073                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11074                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11075                 if (decalsystem->numdecals)
11076                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11077                 if (old.decals)
11078                         Mem_Free(old.decals);
11079                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11080                         decalsystem->element3i[i] = i;
11081                 if (useshortelements)
11082                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11083                                 decalsystem->element3s[i] = i;
11084         }
11085
11086         // grab a decal and search for another free slot for the next one
11087         maxdecals = decalsystem->maxdecals;
11088         decals = decalsystem->decals;
11089         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11090         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11091                 ;
11092         decalsystem->freedecal = i;
11093         if (decalsystem->numdecals <= i)
11094                 decalsystem->numdecals = i + 1;
11095
11096         // initialize the decal
11097         decal->lived = 0;
11098         decal->triangleindex = triangleindex;
11099         decal->surfaceindex = surfaceindex;
11100         decal->decalsequence = decalsequence;
11101         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11102         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11103         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11104         decal->color4ub[0][3] = 255;
11105         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11106         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11107         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11108         decal->color4ub[1][3] = 255;
11109         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11110         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11111         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11112         decal->color4ub[2][3] = 255;
11113         decal->vertex3f[0][0] = v0[0];
11114         decal->vertex3f[0][1] = v0[1];
11115         decal->vertex3f[0][2] = v0[2];
11116         decal->vertex3f[1][0] = v1[0];
11117         decal->vertex3f[1][1] = v1[1];
11118         decal->vertex3f[1][2] = v1[2];
11119         decal->vertex3f[2][0] = v2[0];
11120         decal->vertex3f[2][1] = v2[1];
11121         decal->vertex3f[2][2] = v2[2];
11122         decal->texcoord2f[0][0] = t0[0];
11123         decal->texcoord2f[0][1] = t0[1];
11124         decal->texcoord2f[1][0] = t1[0];
11125         decal->texcoord2f[1][1] = t1[1];
11126         decal->texcoord2f[2][0] = t2[0];
11127         decal->texcoord2f[2][1] = t2[1];
11128 }
11129
11130 extern cvar_t cl_decals_bias;
11131 extern cvar_t cl_decals_models;
11132 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11133 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)
11134 {
11135         matrix4x4_t projection;
11136         decalsystem_t *decalsystem;
11137         qboolean dynamic;
11138         dp_model_t *model;
11139         const float *vertex3f;
11140         const msurface_t *surface;
11141         const msurface_t *surfaces;
11142         const int *surfacelist;
11143         const texture_t *texture;
11144         int numvertices;
11145         int numtriangles;
11146         int numsurfacelist;
11147         int surfacelistindex;
11148         int surfaceindex;
11149         int triangleindex;
11150         int decalsurfaceindex;
11151         int cornerindex;
11152         int index;
11153         int numpoints;
11154         const int *e;
11155         float localorigin[3];
11156         float localnormal[3];
11157         float localmins[3];
11158         float localmaxs[3];
11159         float localsize;
11160         float ilocalsize;
11161         float v[9][3];
11162         float tc[9][2];
11163         float c[9][4];
11164         //float normal[3];
11165         float planes[6][4];
11166         float f;
11167         float points[2][9][3];
11168         float angles[3];
11169         float temp[3];
11170
11171         decalsystem = &ent->decalsystem;
11172         model = ent->model;
11173         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11174         {
11175                 R_DecalSystem_Reset(&ent->decalsystem);
11176                 return;
11177         }
11178
11179         if (!model->brush.data_nodes && !cl_decals_models.integer)
11180         {
11181                 if (decalsystem->model)
11182                         R_DecalSystem_Reset(decalsystem);
11183                 return;
11184         }
11185
11186         if (decalsystem->model != model)
11187                 R_DecalSystem_Reset(decalsystem);
11188         decalsystem->model = model;
11189
11190         RSurf_ActiveModelEntity(ent, false, false, false);
11191
11192         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11193         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11194         VectorNormalize(localnormal);
11195         localsize = worldsize*rsurface.inversematrixscale;
11196         ilocalsize = 1.0f / localsize;
11197         localmins[0] = localorigin[0] - localsize;
11198         localmins[1] = localorigin[1] - localsize;
11199         localmins[2] = localorigin[2] - localsize;
11200         localmaxs[0] = localorigin[0] + localsize;
11201         localmaxs[1] = localorigin[1] + localsize;
11202         localmaxs[2] = localorigin[2] + localsize;
11203
11204         //VectorCopy(localnormal, planes[4]);
11205         //VectorVectors(planes[4], planes[2], planes[0]);
11206         AnglesFromVectors(angles, localnormal, NULL, false);
11207         AngleVectors(angles, planes[0], planes[2], planes[4]);
11208         VectorNegate(planes[0], planes[1]);
11209         VectorNegate(planes[2], planes[3]);
11210         VectorNegate(planes[4], planes[5]);
11211         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11212         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11213         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11214         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11215         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11216         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11217
11218 #if 1
11219 // works
11220 {
11221         matrix4x4_t forwardprojection;
11222         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11223         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11224 }
11225 #else
11226 // broken
11227 {
11228         float projectionvector[4][3];
11229         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11230         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11231         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11232         projectionvector[0][0] = planes[0][0] * ilocalsize;
11233         projectionvector[0][1] = planes[1][0] * ilocalsize;
11234         projectionvector[0][2] = planes[2][0] * ilocalsize;
11235         projectionvector[1][0] = planes[0][1] * ilocalsize;
11236         projectionvector[1][1] = planes[1][1] * ilocalsize;
11237         projectionvector[1][2] = planes[2][1] * ilocalsize;
11238         projectionvector[2][0] = planes[0][2] * ilocalsize;
11239         projectionvector[2][1] = planes[1][2] * ilocalsize;
11240         projectionvector[2][2] = planes[2][2] * ilocalsize;
11241         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11242         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11243         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11244         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11245 }
11246 #endif
11247
11248         dynamic = model->surfmesh.isanimated;
11249         vertex3f = rsurface.modelvertex3f;
11250         numsurfacelist = model->nummodelsurfaces;
11251         surfacelist = model->sortedmodelsurfaces;
11252         surfaces = model->data_surfaces;
11253         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11254         {
11255                 surfaceindex = surfacelist[surfacelistindex];
11256                 surface = surfaces + surfaceindex;
11257                 // skip transparent surfaces
11258                 texture = surface->texture;
11259                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11260                         continue;
11261                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11262                         continue;
11263                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11264                         continue;
11265                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11266                 numvertices = surface->num_vertices;
11267                 numtriangles = surface->num_triangles;
11268                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11269                 {
11270                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11271                         {
11272                                 index = 3*e[cornerindex];
11273                                 VectorCopy(vertex3f + index, v[cornerindex]);
11274                         }
11275                         // cull backfaces
11276                         //TriangleNormal(v[0], v[1], v[2], normal);
11277                         //if (DotProduct(normal, localnormal) < 0.0f)
11278                         //      continue;
11279                         // clip by each of the box planes formed from the projection matrix
11280                         // if anything survives, we emit the decal
11281                         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]);
11282                         if (numpoints < 3)
11283                                 continue;
11284                         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]);
11285                         if (numpoints < 3)
11286                                 continue;
11287                         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]);
11288                         if (numpoints < 3)
11289                                 continue;
11290                         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]);
11291                         if (numpoints < 3)
11292                                 continue;
11293                         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]);
11294                         if (numpoints < 3)
11295                                 continue;
11296                         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]);
11297                         if (numpoints < 3)
11298                                 continue;
11299                         // some part of the triangle survived, so we have to accept it...
11300                         if (dynamic)
11301                         {
11302                                 // dynamic always uses the original triangle
11303                                 numpoints = 3;
11304                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11305                                 {
11306                                         index = 3*e[cornerindex];
11307                                         VectorCopy(vertex3f + index, v[cornerindex]);
11308                                 }
11309                         }
11310                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11311                         {
11312                                 // convert vertex positions to texcoords
11313                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11314                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11315                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11316                                 // calculate distance fade from the projection origin
11317                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11318                                 f = bound(0.0f, f, 1.0f);
11319                                 c[cornerindex][0] = r * f;
11320                                 c[cornerindex][1] = g * f;
11321                                 c[cornerindex][2] = b * f;
11322                                 c[cornerindex][3] = 1.0f;
11323                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11324                         }
11325                         if (dynamic)
11326                                 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);
11327                         else
11328                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11329                                         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);
11330                 }
11331         }
11332 }
11333
11334 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11335 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)
11336 {
11337         int renderentityindex;
11338         float worldmins[3];
11339         float worldmaxs[3];
11340         entity_render_t *ent;
11341
11342         if (!cl_decals_newsystem.integer)
11343                 return;
11344
11345         worldmins[0] = worldorigin[0] - worldsize;
11346         worldmins[1] = worldorigin[1] - worldsize;
11347         worldmins[2] = worldorigin[2] - worldsize;
11348         worldmaxs[0] = worldorigin[0] + worldsize;
11349         worldmaxs[1] = worldorigin[1] + worldsize;
11350         worldmaxs[2] = worldorigin[2] + worldsize;
11351
11352         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11353
11354         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11355         {
11356                 ent = r_refdef.scene.entities[renderentityindex];
11357                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11358                         continue;
11359
11360                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11361         }
11362 }
11363
11364 typedef struct r_decalsystem_splatqueue_s
11365 {
11366         vec3_t worldorigin;
11367         vec3_t worldnormal;
11368         float color[4];
11369         float tcrange[4];
11370         float worldsize;
11371         int decalsequence;
11372 }
11373 r_decalsystem_splatqueue_t;
11374
11375 int r_decalsystem_numqueued = 0;
11376 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11377
11378 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)
11379 {
11380         r_decalsystem_splatqueue_t *queue;
11381
11382         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11383                 return;
11384
11385         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11386         VectorCopy(worldorigin, queue->worldorigin);
11387         VectorCopy(worldnormal, queue->worldnormal);
11388         Vector4Set(queue->color, r, g, b, a);
11389         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11390         queue->worldsize = worldsize;
11391         queue->decalsequence = cl.decalsequence++;
11392 }
11393
11394 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11395 {
11396         int i;
11397         r_decalsystem_splatqueue_t *queue;
11398
11399         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11400                 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);
11401         r_decalsystem_numqueued = 0;
11402 }
11403
11404 extern cvar_t cl_decals_max;
11405 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11406 {
11407         int i;
11408         decalsystem_t *decalsystem = &ent->decalsystem;
11409         int numdecals;
11410         int killsequence;
11411         tridecal_t *decal;
11412         float frametime;
11413         float lifetime;
11414
11415         if (!decalsystem->numdecals)
11416                 return;
11417
11418         if (r_showsurfaces.integer)
11419                 return;
11420
11421         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11422         {
11423                 R_DecalSystem_Reset(decalsystem);
11424                 return;
11425         }
11426
11427         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11428         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11429
11430         if (decalsystem->lastupdatetime)
11431                 frametime = (cl.time - decalsystem->lastupdatetime);
11432         else
11433                 frametime = 0;
11434         decalsystem->lastupdatetime = cl.time;
11435         decal = decalsystem->decals;
11436         numdecals = decalsystem->numdecals;
11437
11438         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11439         {
11440                 if (decal->color4ub[0][3])
11441                 {
11442                         decal->lived += frametime;
11443                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11444                         {
11445                                 memset(decal, 0, sizeof(*decal));
11446                                 if (decalsystem->freedecal > i)
11447                                         decalsystem->freedecal = i;
11448                         }
11449                 }
11450         }
11451         decal = decalsystem->decals;
11452         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11453                 numdecals--;
11454
11455         // collapse the array by shuffling the tail decals into the gaps
11456         for (;;)
11457         {
11458                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11459                         decalsystem->freedecal++;
11460                 if (decalsystem->freedecal == numdecals)
11461                         break;
11462                 decal[decalsystem->freedecal] = decal[--numdecals];
11463         }
11464
11465         decalsystem->numdecals = numdecals;
11466
11467         if (numdecals <= 0)
11468         {
11469                 // if there are no decals left, reset decalsystem
11470                 R_DecalSystem_Reset(decalsystem);
11471         }
11472 }
11473
11474 extern skinframe_t *decalskinframe;
11475 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11476 {
11477         int i;
11478         decalsystem_t *decalsystem = &ent->decalsystem;
11479         int numdecals;
11480         tridecal_t *decal;
11481         float fadedelay;
11482         float faderate;
11483         float alpha;
11484         float *v3f;
11485         float *c4f;
11486         float *t2f;
11487         const int *e;
11488         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11489         int numtris = 0;
11490
11491         numdecals = decalsystem->numdecals;
11492         if (!numdecals)
11493                 return;
11494
11495         if (r_showsurfaces.integer)
11496                 return;
11497
11498         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11499         {
11500                 R_DecalSystem_Reset(decalsystem);
11501                 return;
11502         }
11503
11504         // if the model is static it doesn't matter what value we give for
11505         // wantnormals and wanttangents, so this logic uses only rules applicable
11506         // to a model, knowing that they are meaningless otherwise
11507         if (ent == r_refdef.scene.worldentity)
11508                 RSurf_ActiveWorldEntity();
11509         else
11510                 RSurf_ActiveModelEntity(ent, false, false, false);
11511
11512         decalsystem->lastupdatetime = cl.time;
11513         decal = decalsystem->decals;
11514
11515         fadedelay = cl_decals_time.value;
11516         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11517
11518         // update vertex positions for animated models
11519         v3f = decalsystem->vertex3f;
11520         c4f = decalsystem->color4f;
11521         t2f = decalsystem->texcoord2f;
11522         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11523         {
11524                 if (!decal->color4ub[0][3])
11525                         continue;
11526
11527                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11528                         continue;
11529
11530                 // update color values for fading decals
11531                 if (decal->lived >= cl_decals_time.value)
11532                 {
11533                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11534                         alpha *= (1.0f/255.0f);
11535                 }
11536                 else
11537                         alpha = 1.0f/255.0f;
11538
11539                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11540                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11541                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11542                 c4f[ 3] = 1;
11543                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11544                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11545                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11546                 c4f[ 7] = 1;
11547                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11548                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11549                 c4f[10] = decal->color4ub[2][2] * alpha;
11550                 c4f[11] = 1;
11551
11552                 t2f[0] = decal->texcoord2f[0][0];
11553                 t2f[1] = decal->texcoord2f[0][1];
11554                 t2f[2] = decal->texcoord2f[1][0];
11555                 t2f[3] = decal->texcoord2f[1][1];
11556                 t2f[4] = decal->texcoord2f[2][0];
11557                 t2f[5] = decal->texcoord2f[2][1];
11558
11559                 // update vertex positions for animated models
11560                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11561                 {
11562                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11563                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11564                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11565                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11566                 }
11567                 else
11568                 {
11569                         VectorCopy(decal->vertex3f[0], v3f);
11570                         VectorCopy(decal->vertex3f[1], v3f + 3);
11571                         VectorCopy(decal->vertex3f[2], v3f + 6);
11572                 }
11573
11574                 v3f += 9;
11575                 c4f += 12;
11576                 t2f += 6;
11577                 numtris++;
11578         }
11579
11580         if (numtris > 0)
11581         {
11582                 r_refdef.stats.drawndecals += numtris;
11583
11584                 if (r_refdef.fogenabled)
11585                 {
11586                         switch(vid.renderpath)
11587                         {
11588                         case RENDERPATH_GL20:
11589                         case RENDERPATH_CGGL:
11590                         case RENDERPATH_GL13:
11591                         case RENDERPATH_GL11:
11592                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11593                                 {
11594                                         alpha = RSurf_FogVertex(v3f);
11595                                         c4f[0] *= alpha;
11596                                         c4f[1] *= alpha;
11597                                         c4f[2] *= alpha;
11598                                 }
11599                                 break;
11600                         }
11601                 }
11602
11603                 // now render the decals all at once
11604                 // (this assumes they all use one particle font texture!)
11605                 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);
11606                 R_Mesh_ResetTextureState();
11607                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11608                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11609                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11610                 GL_DepthMask(false);
11611                 GL_DepthRange(0, 1);
11612                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11613                 GL_DepthTest(true);
11614                 GL_CullFace(GL_NONE);
11615                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11616                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11617                 GL_LockArrays(0, numtris * 3);
11618                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11619                 GL_LockArrays(0, 0);
11620         }
11621 }
11622
11623 static void R_DrawModelDecals(void)
11624 {
11625         int i, numdecals;
11626
11627         // fade faster when there are too many decals
11628         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11629         for (i = 0;i < r_refdef.scene.numentities;i++)
11630                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11631
11632         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11633         for (i = 0;i < r_refdef.scene.numentities;i++)
11634                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11635                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11636
11637         R_DecalSystem_ApplySplatEntitiesQueue();
11638
11639         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11640         for (i = 0;i < r_refdef.scene.numentities;i++)
11641                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11642
11643         r_refdef.stats.totaldecals += numdecals;
11644
11645         if (r_showsurfaces.integer)
11646                 return;
11647
11648         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11649
11650         for (i = 0;i < r_refdef.scene.numentities;i++)
11651         {
11652                 if (!r_refdef.viewcache.entityvisible[i])
11653                         continue;
11654                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11655                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11656         }
11657 }
11658
11659 void R_DrawDebugModel(void)
11660 {
11661         entity_render_t *ent = rsurface.entity;
11662         int i, j, k, l, flagsmask;
11663         const int *elements;
11664         q3mbrush_t *brush;
11665         const msurface_t *surface;
11666         dp_model_t *model = ent->model;
11667         vec3_t v;
11668
11669         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11670
11671         R_Mesh_ColorPointer(NULL, 0, 0);
11672         R_Mesh_ResetTextureState();
11673         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11674         GL_DepthRange(0, 1);
11675         GL_DepthTest(!r_showdisabledepthtest.integer);
11676         GL_DepthMask(false);
11677         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11678
11679         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11680         {
11681                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11682                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11683                 {
11684                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11685                         {
11686                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11687                                 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);
11688                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11689                         }
11690                 }
11691                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11692                 {
11693                         if (surface->num_collisiontriangles)
11694                         {
11695                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11696                                 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);
11697                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11698                         }
11699                 }
11700         }
11701
11702         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11703
11704         if (r_showtris.integer || r_shownormals.integer)
11705         {
11706                 if (r_showdisabledepthtest.integer)
11707                 {
11708                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11709                         GL_DepthMask(false);
11710                 }
11711                 else
11712                 {
11713                         GL_BlendFunc(GL_ONE, GL_ZERO);
11714                         GL_DepthMask(true);
11715                 }
11716                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11717                 {
11718                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11719                                 continue;
11720                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11721                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11722                         {
11723                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11724                                 if (r_showtris.value > 0)
11725                                 {
11726                                         if (!rsurface.texture->currentlayers->depthmask)
11727                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11728                                         else if (ent == r_refdef.scene.worldentity)
11729                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11730                                         else
11731                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11732                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11733                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11734                                         R_Mesh_ColorPointer(NULL, 0, 0);
11735                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11736                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11737                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11738                                         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);
11739                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11740                                         CHECKGLERROR
11741                                 }
11742                                 if (r_shownormals.value < 0)
11743                                 {
11744                                         qglBegin(GL_LINES);
11745                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11746                                         {
11747                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11748                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11749                                                 qglVertex3f(v[0], v[1], v[2]);
11750                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11751                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11752                                                 qglVertex3f(v[0], v[1], v[2]);
11753                                         }
11754                                         qglEnd();
11755                                         CHECKGLERROR
11756                                 }
11757                                 if (r_shownormals.value > 0)
11758                                 {
11759                                         qglBegin(GL_LINES);
11760                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11761                                         {
11762                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11763                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11764                                                 qglVertex3f(v[0], v[1], v[2]);
11765                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11766                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11767                                                 qglVertex3f(v[0], v[1], v[2]);
11768                                         }
11769                                         qglEnd();
11770                                         CHECKGLERROR
11771                                         qglBegin(GL_LINES);
11772                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11773                                         {
11774                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11775                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11776                                                 qglVertex3f(v[0], v[1], v[2]);
11777                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11778                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11779                                                 qglVertex3f(v[0], v[1], v[2]);
11780                                         }
11781                                         qglEnd();
11782                                         CHECKGLERROR
11783                                         qglBegin(GL_LINES);
11784                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11785                                         {
11786                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11787                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11788                                                 qglVertex3f(v[0], v[1], v[2]);
11789                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11790                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11791                                                 qglVertex3f(v[0], v[1], v[2]);
11792                                         }
11793                                         qglEnd();
11794                                         CHECKGLERROR
11795                                 }
11796                         }
11797                 }
11798                 rsurface.texture = NULL;
11799         }
11800 }
11801
11802 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11803 int r_maxsurfacelist = 0;
11804 const msurface_t **r_surfacelist = NULL;
11805 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11806 {
11807         int i, j, endj, f, flagsmask;
11808         texture_t *t;
11809         dp_model_t *model = r_refdef.scene.worldmodel;
11810         msurface_t *surfaces;
11811         unsigned char *update;
11812         int numsurfacelist = 0;
11813         if (model == NULL)
11814                 return;
11815
11816         if (r_maxsurfacelist < model->num_surfaces)
11817         {
11818                 r_maxsurfacelist = model->num_surfaces;
11819                 if (r_surfacelist)
11820                         Mem_Free((msurface_t**)r_surfacelist);
11821                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11822         }
11823
11824         RSurf_ActiveWorldEntity();
11825
11826         surfaces = model->data_surfaces;
11827         update = model->brushq1.lightmapupdateflags;
11828
11829         // update light styles on this submodel
11830         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11831         {
11832                 model_brush_lightstyleinfo_t *style;
11833                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11834                 {
11835                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11836                         {
11837                                 int *list = style->surfacelist;
11838                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11839                                 for (j = 0;j < style->numsurfaces;j++)
11840                                         update[list[j]] = true;
11841                         }
11842                 }
11843         }
11844
11845         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11846
11847         if (debug)
11848         {
11849                 R_DrawDebugModel();
11850                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11851                 return;
11852         }
11853
11854         f = 0;
11855         t = NULL;
11856         rsurface.uselightmaptexture = false;
11857         rsurface.texture = NULL;
11858         rsurface.rtlight = NULL;
11859         numsurfacelist = 0;
11860         // add visible surfaces to draw list
11861         for (i = 0;i < model->nummodelsurfaces;i++)
11862         {
11863                 j = model->sortedmodelsurfaces[i];
11864                 if (r_refdef.viewcache.world_surfacevisible[j])
11865                         r_surfacelist[numsurfacelist++] = surfaces + j;
11866         }
11867         // update lightmaps if needed
11868         if (model->brushq1.firstrender)
11869         {
11870                 model->brushq1.firstrender = false;
11871                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11872                         if (update[j])
11873                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11874         }
11875         else if (update)
11876         {
11877                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11878                         if (r_refdef.viewcache.world_surfacevisible[j])
11879                                 if (update[j])
11880                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11881         }
11882         // don't do anything if there were no surfaces
11883         if (!numsurfacelist)
11884         {
11885                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11886                 return;
11887         }
11888         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11889         GL_AlphaTest(false);
11890
11891         // add to stats if desired
11892         if (r_speeds.integer && !skysurfaces && !depthonly)
11893         {
11894                 r_refdef.stats.world_surfaces += numsurfacelist;
11895                 for (j = 0;j < numsurfacelist;j++)
11896                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11897         }
11898
11899         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11900 }
11901
11902 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11903 {
11904         int i, j, endj, f, flagsmask;
11905         texture_t *t;
11906         dp_model_t *model = ent->model;
11907         msurface_t *surfaces;
11908         unsigned char *update;
11909         int numsurfacelist = 0;
11910         if (model == NULL)
11911                 return;
11912
11913         if (r_maxsurfacelist < model->num_surfaces)
11914         {
11915                 r_maxsurfacelist = model->num_surfaces;
11916                 if (r_surfacelist)
11917                         Mem_Free((msurface_t **)r_surfacelist);
11918                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11919         }
11920
11921         // if the model is static it doesn't matter what value we give for
11922         // wantnormals and wanttangents, so this logic uses only rules applicable
11923         // to a model, knowing that they are meaningless otherwise
11924         if (ent == r_refdef.scene.worldentity)
11925                 RSurf_ActiveWorldEntity();
11926         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11927                 RSurf_ActiveModelEntity(ent, false, false, false);
11928         else if (prepass)
11929                 RSurf_ActiveModelEntity(ent, true, true, true);
11930         else if (depthonly)
11931                 RSurf_ActiveModelEntity(ent, false, false, false);
11932         else
11933         {
11934                 switch (vid.renderpath)
11935                 {
11936                 case RENDERPATH_GL20:
11937                 case RENDERPATH_CGGL:
11938                         RSurf_ActiveModelEntity(ent, true, true, false);
11939                         break;
11940                 case RENDERPATH_GL13:
11941                 case RENDERPATH_GL11:
11942                         RSurf_ActiveModelEntity(ent, true, false, false);
11943                         break;
11944                 }
11945         }
11946
11947         surfaces = model->data_surfaces;
11948         update = model->brushq1.lightmapupdateflags;
11949
11950         // update light styles
11951         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11952         {
11953                 model_brush_lightstyleinfo_t *style;
11954                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11955                 {
11956                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11957                         {
11958                                 int *list = style->surfacelist;
11959                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11960                                 for (j = 0;j < style->numsurfaces;j++)
11961                                         update[list[j]] = true;
11962                         }
11963                 }
11964         }
11965
11966         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11967
11968         if (debug)
11969         {
11970                 R_DrawDebugModel();
11971                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11972                 return;
11973         }
11974
11975         f = 0;
11976         t = NULL;
11977         rsurface.uselightmaptexture = false;
11978         rsurface.texture = NULL;
11979         rsurface.rtlight = NULL;
11980         numsurfacelist = 0;
11981         // add visible surfaces to draw list
11982         for (i = 0;i < model->nummodelsurfaces;i++)
11983                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11984         // don't do anything if there were no surfaces
11985         if (!numsurfacelist)
11986         {
11987                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11988                 return;
11989         }
11990         // update lightmaps if needed
11991         if (update)
11992         {
11993                 int updated = 0;
11994                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11995                 {
11996                         if (update[j])
11997                         {
11998                                 updated++;
11999                                 R_BuildLightMap(ent, surfaces + j);
12000                         }
12001                 }
12002         }
12003         if (update)
12004                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12005                         if (update[j])
12006                                 R_BuildLightMap(ent, surfaces + j);
12007         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12008         GL_AlphaTest(false);
12009
12010         // add to stats if desired
12011         if (r_speeds.integer && !skysurfaces && !depthonly)
12012         {
12013                 r_refdef.stats.entities_surfaces += numsurfacelist;
12014                 for (j = 0;j < numsurfacelist;j++)
12015                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12016         }
12017
12018         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12019 }
12020
12021 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12022 {
12023         static texture_t texture;
12024         static msurface_t surface;
12025         const msurface_t *surfacelist = &surface;
12026
12027         // fake enough texture and surface state to render this geometry
12028
12029         texture.update_lastrenderframe = -1; // regenerate this texture
12030         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12031         texture.currentskinframe = skinframe;
12032         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12033         texture.specularscalemod = 1;
12034         texture.specularpowermod = 1;
12035
12036         surface.texture = &texture;
12037         surface.num_triangles = numtriangles;
12038         surface.num_firsttriangle = firsttriangle;
12039         surface.num_vertices = numvertices;
12040         surface.num_firstvertex = firstvertex;
12041
12042         // now render it
12043         rsurface.texture = R_GetCurrentTexture(surface.texture);
12044         rsurface.uselightmaptexture = false;
12045         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12046 }
12047
12048 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)
12049 {
12050         static msurface_t surface;
12051         const msurface_t *surfacelist = &surface;
12052
12053         // fake enough texture and surface state to render this geometry
12054
12055         surface.texture = texture;
12056         surface.num_triangles = numtriangles;
12057         surface.num_firsttriangle = firsttriangle;
12058         surface.num_vertices = numvertices;
12059         surface.num_firstvertex = firstvertex;
12060
12061         // now render it
12062         rsurface.texture = R_GetCurrentTexture(surface.texture);
12063         rsurface.uselightmaptexture = false;
12064         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12065 }