]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
UNMERGE
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_frame = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
73 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
74 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
96 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
102
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
111
112 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
113 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
114
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
118
119 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
125 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
126 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
127 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
128
129 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
134
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
139
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
147
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
152
153 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
154
155 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
156
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
158
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_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         r_frame++; // used only by R_GetCurrentTexture
7241
7242         R_ResetViewRendering3D();
7243
7244         R_ClearScreen(r_refdef.fogenabled);
7245         if (r_timereport_active)
7246                 R_TimeReport("viewclear");
7247 }
7248
7249 static void R_BlendView(void)
7250 {
7251         unsigned int permutation;
7252         float uservecs[4][4];
7253
7254         switch (vid.renderpath)
7255         {
7256         case RENDERPATH_GL20:
7257         case RENDERPATH_CGGL:
7258                 permutation =
7259                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7260                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7261                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7262                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7263                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7264
7265                 if (r_bloomstate.texture_screen)
7266                 {
7267                         // make sure the buffer is available
7268                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7269
7270                         R_ResetViewRendering2D();
7271                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7272                         R_Mesh_ColorPointer(NULL, 0, 0);
7273
7274                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7275                         {
7276                                 // declare variables
7277                                 float speed;
7278                                 static float avgspeed;
7279
7280                                 speed = VectorLength(cl.movement_velocity);
7281
7282                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7283                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7284
7285                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7286                                 speed = bound(0, speed, 1);
7287                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7288
7289                                 // calculate values into a standard alpha
7290                                 cl.motionbluralpha = 1 - exp(-
7291                                                 (
7292                                                  (r_motionblur.value * speed / 80)
7293                                                  +
7294                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7295                                                 )
7296                                                 /
7297                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7298                                            );
7299
7300                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7301                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7302                                 // apply the blur
7303                                 if (cl.motionbluralpha > 0)
7304                                 {
7305                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7306                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7307                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7308                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7309                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7310                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7311                                 }
7312                         }
7313
7314                         // copy view into the screen texture
7315                         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);
7316                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7317                 }
7318                 else if (!r_bloomstate.texture_bloom)
7319                 {
7320                         // we may still have to do view tint...
7321                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7322                         {
7323                                 // apply a color tint to the whole view
7324                                 R_ResetViewRendering2D();
7325                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7326                                 R_Mesh_ColorPointer(NULL, 0, 0);
7327                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7328                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7329                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7330                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7331                         }
7332                         break; // no screen processing, no bloom, skip it
7333                 }
7334
7335                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7336                 {
7337                         // render simple bloom effect
7338                         // copy the screen and shrink it and darken it for the bloom process
7339                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7340                         // make the bloom texture
7341                         R_Bloom_MakeTexture();
7342                 }
7343
7344 #if _MSC_VER >= 1400
7345 #define sscanf sscanf_s
7346 #endif
7347                 memset(uservecs, 0, sizeof(uservecs));
7348                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7349                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7350                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7351                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7352
7353                 R_ResetViewRendering2D();
7354                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7355                 R_Mesh_ColorPointer(NULL, 0, 0);
7356                 GL_Color(1, 1, 1, 1);
7357                 GL_BlendFunc(GL_ONE, GL_ZERO);
7358                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7359                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7360
7361                 switch(vid.renderpath)
7362                 {
7363                 case RENDERPATH_GL20:
7364                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7365                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7366                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7367                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7368                         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]);
7369                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7370                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7371                         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]);
7372                         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]);
7373                         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]);
7374                         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]);
7375                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7376                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7377                         break;
7378                 case RENDERPATH_CGGL:
7379 #ifdef SUPPORTCG
7380                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7381                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7382                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7383                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7384                         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
7385                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7386                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7387                         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
7388                         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
7389                         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
7390                         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
7391                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7392                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7393 #endif
7394                         break;
7395                 default:
7396                         break;
7397                 }
7398                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7399                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7400                 break;
7401         case RENDERPATH_GL13:
7402         case RENDERPATH_GL11:
7403                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7404                 {
7405                         // apply a color tint to the whole view
7406                         R_ResetViewRendering2D();
7407                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7408                         R_Mesh_ColorPointer(NULL, 0, 0);
7409                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7410                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7411                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7412                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7413                 }
7414                 break;
7415         }
7416 }
7417
7418 matrix4x4_t r_waterscrollmatrix;
7419
7420 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7421 {
7422         if (r_refdef.fog_density)
7423         {
7424                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7425                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7426                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7427
7428                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7429                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7430                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7431                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7432
7433                 {
7434                         vec3_t fogvec;
7435                         VectorCopy(r_refdef.fogcolor, fogvec);
7436                         //   color.rgb *= ContrastBoost * SceneBrightness;
7437                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7438                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7439                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7440                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7441                 }
7442         }
7443 }
7444
7445 void R_UpdateVariables(void)
7446 {
7447         R_Textures_Frame();
7448
7449         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7450
7451         r_refdef.farclip = r_farclip_base.value;
7452         if (r_refdef.scene.worldmodel)
7453                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7454         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7455
7456         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7457                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7458         r_refdef.polygonfactor = 0;
7459         r_refdef.polygonoffset = 0;
7460         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7461         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7462
7463         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7464         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7465         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7466         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7467         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7468         if (r_showsurfaces.integer)
7469         {
7470                 r_refdef.scene.rtworld = false;
7471                 r_refdef.scene.rtworldshadows = false;
7472                 r_refdef.scene.rtdlight = false;
7473                 r_refdef.scene.rtdlightshadows = false;
7474                 r_refdef.lightmapintensity = 0;
7475         }
7476
7477         if (gamemode == GAME_NEHAHRA)
7478         {
7479                 if (gl_fogenable.integer)
7480                 {
7481                         r_refdef.oldgl_fogenable = true;
7482                         r_refdef.fog_density = gl_fogdensity.value;
7483                         r_refdef.fog_red = gl_fogred.value;
7484                         r_refdef.fog_green = gl_foggreen.value;
7485                         r_refdef.fog_blue = gl_fogblue.value;
7486                         r_refdef.fog_alpha = 1;
7487                         r_refdef.fog_start = 0;
7488                         r_refdef.fog_end = gl_skyclip.value;
7489                         r_refdef.fog_height = 1<<30;
7490                         r_refdef.fog_fadedepth = 128;
7491                 }
7492                 else if (r_refdef.oldgl_fogenable)
7493                 {
7494                         r_refdef.oldgl_fogenable = false;
7495                         r_refdef.fog_density = 0;
7496                         r_refdef.fog_red = 0;
7497                         r_refdef.fog_green = 0;
7498                         r_refdef.fog_blue = 0;
7499                         r_refdef.fog_alpha = 0;
7500                         r_refdef.fog_start = 0;
7501                         r_refdef.fog_end = 0;
7502                         r_refdef.fog_height = 1<<30;
7503                         r_refdef.fog_fadedepth = 128;
7504                 }
7505         }
7506
7507         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7508         r_refdef.fog_start = max(0, r_refdef.fog_start);
7509         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7510
7511         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7512
7513         if (r_refdef.fog_density && r_drawfog.integer)
7514         {
7515                 r_refdef.fogenabled = true;
7516                 // this is the point where the fog reaches 0.9986 alpha, which we
7517                 // consider a good enough cutoff point for the texture
7518                 // (0.9986 * 256 == 255.6)
7519                 if (r_fog_exp2.integer)
7520                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7521                 else
7522                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7523                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7524                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7525                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7526                 // fog color was already set
7527                 // update the fog texture
7528                 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)
7529                         R_BuildFogTexture();
7530         }
7531         else
7532                 r_refdef.fogenabled = false;
7533
7534         switch(vid.renderpath)
7535         {
7536         case RENDERPATH_GL20:
7537         case RENDERPATH_CGGL:
7538                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7539                 {
7540                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7541                         {
7542                                 // build GLSL gamma texture
7543 #define RAMPWIDTH 256
7544                                 unsigned short ramp[RAMPWIDTH * 3];
7545                                 unsigned char rampbgr[RAMPWIDTH][4];
7546                                 int i;
7547
7548                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7549
7550                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7551                                 for(i = 0; i < RAMPWIDTH; ++i)
7552                                 {
7553                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7554                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7555                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7556                                         rampbgr[i][3] = 0;
7557                                 }
7558                                 if (r_texture_gammaramps)
7559                                 {
7560                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7561                                 }
7562                                 else
7563                                 {
7564                                         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);
7565                                 }
7566                         }
7567                 }
7568                 else
7569                 {
7570                         // remove GLSL gamma texture
7571                 }
7572                 break;
7573         case RENDERPATH_GL13:
7574         case RENDERPATH_GL11:
7575                 break;
7576         }
7577 }
7578
7579 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7580 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7581 /*
7582 ================
7583 R_SelectScene
7584 ================
7585 */
7586 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7587         if( scenetype != r_currentscenetype ) {
7588                 // store the old scenetype
7589                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7590                 r_currentscenetype = scenetype;
7591                 // move in the new scene
7592                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7593         }
7594 }
7595
7596 /*
7597 ================
7598 R_GetScenePointer
7599 ================
7600 */
7601 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7602 {
7603         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7604         if( scenetype == r_currentscenetype ) {
7605                 return &r_refdef.scene;
7606         } else {
7607                 return &r_scenes_store[ scenetype ];
7608         }
7609 }
7610
7611 /*
7612 ================
7613 R_RenderView
7614 ================
7615 */
7616 void R_RenderView(void)
7617 {
7618         if (r_timereport_active)
7619                 R_TimeReport("start");
7620         r_frame++; // used only by R_GetCurrentTexture
7621         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7622
7623         if (!r_drawentities.integer)
7624                 r_refdef.scene.numentities = 0;
7625
7626         R_AnimCache_ClearCache();
7627         R_FrameData_NewFrame();
7628
7629         if (r_refdef.view.isoverlay)
7630         {
7631                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7632                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7633                 R_TimeReport("depthclear");
7634
7635                 r_refdef.view.showdebug = false;
7636
7637                 r_waterstate.enabled = false;
7638                 r_waterstate.numwaterplanes = 0;
7639
7640                 R_RenderScene();
7641
7642                 CHECKGLERROR
7643                 return;
7644         }
7645
7646         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7647                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7648
7649         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7650
7651         // break apart the view matrix into vectors for various purposes
7652         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7653         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7654         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7655         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7656         // make an inverted copy of the view matrix for tracking sprites
7657         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7658
7659         R_Shadow_UpdateWorldLightSelection();
7660
7661         R_Bloom_StartFrame();
7662         R_Water_StartFrame();
7663
7664         CHECKGLERROR
7665         if (r_timereport_active)
7666                 R_TimeReport("viewsetup");
7667
7668         R_ResetViewRendering3D();
7669
7670         if (r_refdef.view.clear || r_refdef.fogenabled)
7671         {
7672                 R_ClearScreen(r_refdef.fogenabled);
7673                 if (r_timereport_active)
7674                         R_TimeReport("viewclear");
7675         }
7676         r_refdef.view.clear = true;
7677
7678         // this produces a bloom texture to be used in R_BlendView() later
7679         if (r_hdr.integer && r_bloomstate.bloomwidth)
7680                 R_HDR_RenderBloomTexture();
7681
7682         r_refdef.view.showdebug = true;
7683
7684         R_View_Update();
7685         if (r_timereport_active)
7686                 R_TimeReport("visibility");
7687
7688         r_waterstate.numwaterplanes = 0;
7689         if (r_waterstate.enabled)
7690                 R_RenderWaterPlanes();
7691
7692         R_RenderScene();
7693         r_waterstate.numwaterplanes = 0;
7694
7695         R_BlendView();
7696         if (r_timereport_active)
7697                 R_TimeReport("blendview");
7698
7699         GL_Scissor(0, 0, vid.width, vid.height);
7700         GL_ScissorTest(false);
7701         CHECKGLERROR
7702 }
7703
7704 void R_RenderWaterPlanes(void)
7705 {
7706         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7707         {
7708                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7709                 if (r_timereport_active)
7710                         R_TimeReport("waterworld");
7711         }
7712
7713         // don't let sound skip if going slow
7714         if (r_refdef.scene.extraupdate)
7715                 S_ExtraUpdate ();
7716
7717         R_DrawModelsAddWaterPlanes();
7718         if (r_timereport_active)
7719                 R_TimeReport("watermodels");
7720
7721         if (r_waterstate.numwaterplanes)
7722         {
7723                 R_Water_ProcessPlanes();
7724                 if (r_timereport_active)
7725                         R_TimeReport("waterscenes");
7726         }
7727 }
7728
7729 extern void R_DrawLightningBeams (void);
7730 extern void VM_CL_AddPolygonsToMeshQueue (void);
7731 extern void R_DrawPortals (void);
7732 extern cvar_t cl_locs_show;
7733 static void R_DrawLocs(void);
7734 static void R_DrawEntityBBoxes(void);
7735 static void R_DrawModelDecals(void);
7736 extern cvar_t cl_decals_newsystem;
7737 extern qboolean r_shadow_usingdeferredprepass;
7738 void R_RenderScene(void)
7739 {
7740         r_refdef.stats.renders++;
7741
7742         R_UpdateFogColor();
7743
7744         // don't let sound skip if going slow
7745         if (r_refdef.scene.extraupdate)
7746                 S_ExtraUpdate ();
7747
7748         R_MeshQueue_BeginScene();
7749
7750         R_SkyStartFrame();
7751
7752         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);
7753
7754         if (cl.csqc_vidvars.drawworld)
7755         {
7756                 // don't let sound skip if going slow
7757                 if (r_refdef.scene.extraupdate)
7758                         S_ExtraUpdate ();
7759
7760                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7761                 {
7762                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7763                         if (r_timereport_active)
7764                                 R_TimeReport("worldsky");
7765                 }
7766
7767                 if (R_DrawBrushModelsSky() && r_timereport_active)
7768                         R_TimeReport("bmodelsky");
7769
7770                 if (skyrendermasked && skyrenderlater)
7771                 {
7772                         // we have to force off the water clipping plane while rendering sky
7773                         R_SetupView(false);
7774                         R_Sky();
7775                         R_SetupView(true);
7776                         if (r_timereport_active)
7777                                 R_TimeReport("sky");
7778                 }
7779         }
7780
7781         R_AnimCache_CacheVisibleEntities();
7782         if (r_timereport_active)
7783                 R_TimeReport("animation");
7784
7785         R_Shadow_PrepareLights();
7786         if (r_timereport_active)
7787                 R_TimeReport("preparelights");
7788
7789         if (r_shadow_usingdeferredprepass)
7790                 R_Shadow_DrawPrepass();
7791
7792         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7793         {
7794                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7795                 if (r_timereport_active)
7796                         R_TimeReport("worlddepth");
7797         }
7798         if (r_depthfirst.integer >= 2)
7799         {
7800                 R_DrawModelsDepth();
7801                 if (r_timereport_active)
7802                         R_TimeReport("modeldepth");
7803         }
7804
7805         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7806         {
7807                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7808                 if (r_timereport_active)
7809                         R_TimeReport("world");
7810         }
7811
7812         // don't let sound skip if going slow
7813         if (r_refdef.scene.extraupdate)
7814                 S_ExtraUpdate ();
7815
7816         R_DrawModels();
7817         if (r_timereport_active)
7818                 R_TimeReport("models");
7819
7820         // don't let sound skip if going slow
7821         if (r_refdef.scene.extraupdate)
7822                 S_ExtraUpdate ();
7823
7824         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7825         {
7826                 R_DrawModelShadows();
7827                 R_ResetViewRendering3D();
7828                 // don't let sound skip if going slow
7829                 if (r_refdef.scene.extraupdate)
7830                         S_ExtraUpdate ();
7831         }
7832
7833         if (!r_shadow_usingdeferredprepass)
7834         {
7835                 R_Shadow_DrawLights();
7836                 if (r_timereport_active)
7837                         R_TimeReport("rtlights");
7838         }
7839
7840         // don't let sound skip if going slow
7841         if (r_refdef.scene.extraupdate)
7842                 S_ExtraUpdate ();
7843
7844         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7845         {
7846                 R_DrawModelShadows();
7847                 R_ResetViewRendering3D();
7848                 // don't let sound skip if going slow
7849                 if (r_refdef.scene.extraupdate)
7850                         S_ExtraUpdate ();
7851         }
7852
7853         if (cl.csqc_vidvars.drawworld)
7854         {
7855                 if (cl_decals_newsystem.integer)
7856                 {
7857                         R_DrawModelDecals();
7858                         if (r_timereport_active)
7859                                 R_TimeReport("modeldecals");
7860                 }
7861                 else
7862                 {
7863                         R_DrawDecals();
7864                         if (r_timereport_active)
7865                                 R_TimeReport("decals");
7866                 }
7867
7868                 R_DrawParticles();
7869                 if (r_timereport_active)
7870                         R_TimeReport("particles");
7871
7872                 R_DrawExplosions();
7873                 if (r_timereport_active)
7874                         R_TimeReport("explosions");
7875
7876                 R_DrawLightningBeams();
7877                 if (r_timereport_active)
7878                         R_TimeReport("lightning");
7879         }
7880
7881         VM_CL_AddPolygonsToMeshQueue();
7882
7883         if (r_refdef.view.showdebug)
7884         {
7885                 if (cl_locs_show.integer)
7886                 {
7887                         R_DrawLocs();
7888                         if (r_timereport_active)
7889                                 R_TimeReport("showlocs");
7890                 }
7891
7892                 if (r_drawportals.integer)
7893                 {
7894                         R_DrawPortals();
7895                         if (r_timereport_active)
7896                                 R_TimeReport("portals");
7897                 }
7898
7899                 if (r_showbboxes.value > 0)
7900                 {
7901                         R_DrawEntityBBoxes();
7902                         if (r_timereport_active)
7903                                 R_TimeReport("bboxes");
7904                 }
7905         }
7906
7907         R_MeshQueue_RenderTransparent();
7908         if (r_timereport_active)
7909                 R_TimeReport("drawtrans");
7910
7911         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))
7912         {
7913                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7914                 if (r_timereport_active)
7915                         R_TimeReport("worlddebug");
7916                 R_DrawModelsDebug();
7917                 if (r_timereport_active)
7918                         R_TimeReport("modeldebug");
7919         }
7920
7921         if (cl.csqc_vidvars.drawworld)
7922         {
7923                 R_Shadow_DrawCoronas();
7924                 if (r_timereport_active)
7925                         R_TimeReport("coronas");
7926         }
7927
7928         // don't let sound skip if going slow
7929         if (r_refdef.scene.extraupdate)
7930                 S_ExtraUpdate ();
7931
7932         R_ResetViewRendering2D();
7933 }
7934
7935 static const unsigned short bboxelements[36] =
7936 {
7937         5, 1, 3, 5, 3, 7,
7938         6, 2, 0, 6, 0, 4,
7939         7, 3, 2, 7, 2, 6,
7940         4, 0, 1, 4, 1, 5,
7941         4, 5, 7, 4, 7, 6,
7942         1, 0, 2, 1, 2, 3,
7943 };
7944
7945 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7946 {
7947         int i;
7948         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7949
7950         RSurf_ActiveWorldEntity();
7951
7952         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7953         GL_DepthMask(false);
7954         GL_DepthRange(0, 1);
7955         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7956         R_Mesh_ResetTextureState();
7957
7958         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7959         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7960         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7961         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7962         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7963         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7964         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7965         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7966         R_FillColors(color4f, 8, cr, cg, cb, ca);
7967         if (r_refdef.fogenabled)
7968         {
7969                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7970                 {
7971                         f1 = RSurf_FogVertex(v);
7972                         f2 = 1 - f1;
7973                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7974                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7975                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7976                 }
7977         }
7978         R_Mesh_VertexPointer(vertex3f, 0, 0);
7979         R_Mesh_ColorPointer(color4f, 0, 0);
7980         R_Mesh_ResetTextureState();
7981         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7982         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
7983 }
7984
7985 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7986 {
7987         int i;
7988         float color[4];
7989         prvm_edict_t *edict;
7990         prvm_prog_t *prog_save = prog;
7991
7992         // this function draws bounding boxes of server entities
7993         if (!sv.active)
7994                 return;
7995
7996         GL_CullFace(GL_NONE);
7997         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7998
7999         prog = 0;
8000         SV_VM_Begin();
8001         for (i = 0;i < numsurfaces;i++)
8002         {
8003                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8004                 switch ((int)edict->fields.server->solid)
8005                 {
8006                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8007                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8008                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8009                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8010                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8011                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8012                 }
8013                 color[3] *= r_showbboxes.value;
8014                 color[3] = bound(0, color[3], 1);
8015                 GL_DepthTest(!r_showdisabledepthtest.integer);
8016                 GL_CullFace(r_refdef.view.cullface_front);
8017                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8018         }
8019         SV_VM_End();
8020         prog = prog_save;
8021 }
8022
8023 static void R_DrawEntityBBoxes(void)
8024 {
8025         int i;
8026         prvm_edict_t *edict;
8027         vec3_t center;
8028         prvm_prog_t *prog_save = prog;
8029
8030         // this function draws bounding boxes of server entities
8031         if (!sv.active)
8032                 return;
8033
8034         prog = 0;
8035         SV_VM_Begin();
8036         for (i = 0;i < prog->num_edicts;i++)
8037         {
8038                 edict = PRVM_EDICT_NUM(i);
8039                 if (edict->priv.server->free)
8040                         continue;
8041                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8042                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8043                         continue;
8044                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8045                         continue;
8046                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8047                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8048         }
8049         SV_VM_End();
8050         prog = prog_save;
8051 }
8052
8053 static const int nomodelelement3i[24] =
8054 {
8055         5, 2, 0,
8056         5, 1, 2,
8057         5, 0, 3,
8058         5, 3, 1,
8059         0, 2, 4,
8060         2, 1, 4,
8061         3, 0, 4,
8062         1, 3, 4
8063 };
8064
8065 static const unsigned short nomodelelement3s[24] =
8066 {
8067         5, 2, 0,
8068         5, 1, 2,
8069         5, 0, 3,
8070         5, 3, 1,
8071         0, 2, 4,
8072         2, 1, 4,
8073         3, 0, 4,
8074         1, 3, 4
8075 };
8076
8077 static const float nomodelvertex3f[6*3] =
8078 {
8079         -16,   0,   0,
8080          16,   0,   0,
8081           0, -16,   0,
8082           0,  16,   0,
8083           0,   0, -16,
8084           0,   0,  16
8085 };
8086
8087 static const float nomodelcolor4f[6*4] =
8088 {
8089         0.0f, 0.0f, 0.5f, 1.0f,
8090         0.0f, 0.0f, 0.5f, 1.0f,
8091         0.0f, 0.5f, 0.0f, 1.0f,
8092         0.0f, 0.5f, 0.0f, 1.0f,
8093         0.5f, 0.0f, 0.0f, 1.0f,
8094         0.5f, 0.0f, 0.0f, 1.0f
8095 };
8096
8097 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8098 {
8099         int i;
8100         float f1, f2, *c;
8101         float color4f[6*4];
8102
8103         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);
8104
8105         // this is only called once per entity so numsurfaces is always 1, and
8106         // surfacelist is always {0}, so this code does not handle batches
8107
8108         if (rsurface.ent_flags & RENDER_ADDITIVE)
8109         {
8110                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8111                 GL_DepthMask(false);
8112         }
8113         else if (rsurface.colormod[3] < 1)
8114         {
8115                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8116                 GL_DepthMask(false);
8117         }
8118         else
8119         {
8120                 GL_BlendFunc(GL_ONE, GL_ZERO);
8121                 GL_DepthMask(true);
8122         }
8123         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8124         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8125         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8126         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8127         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8128         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8129         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8130         R_Mesh_ColorPointer(color4f, 0, 0);
8131         for (i = 0, c = color4f;i < 6;i++, c += 4)
8132         {
8133                 c[0] *= rsurface.colormod[0];
8134                 c[1] *= rsurface.colormod[1];
8135                 c[2] *= rsurface.colormod[2];
8136                 c[3] *= rsurface.colormod[3];
8137         }
8138         if (r_refdef.fogenabled)
8139         {
8140                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8141                 {
8142                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8143                         f2 = 1 - f1;
8144                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8145                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8146                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8147                 }
8148         }
8149         R_Mesh_ResetTextureState();
8150         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8151 }
8152
8153 void R_DrawNoModel(entity_render_t *ent)
8154 {
8155         vec3_t org;
8156         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8157         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8158                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8159         else
8160                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8161 }
8162
8163 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8164 {
8165         vec3_t right1, right2, diff, normal;
8166
8167         VectorSubtract (org2, org1, normal);
8168
8169         // calculate 'right' vector for start
8170         VectorSubtract (r_refdef.view.origin, org1, diff);
8171         CrossProduct (normal, diff, right1);
8172         VectorNormalize (right1);
8173
8174         // calculate 'right' vector for end
8175         VectorSubtract (r_refdef.view.origin, org2, diff);
8176         CrossProduct (normal, diff, right2);
8177         VectorNormalize (right2);
8178
8179         vert[ 0] = org1[0] + width * right1[0];
8180         vert[ 1] = org1[1] + width * right1[1];
8181         vert[ 2] = org1[2] + width * right1[2];
8182         vert[ 3] = org1[0] - width * right1[0];
8183         vert[ 4] = org1[1] - width * right1[1];
8184         vert[ 5] = org1[2] - width * right1[2];
8185         vert[ 6] = org2[0] - width * right2[0];
8186         vert[ 7] = org2[1] - width * right2[1];
8187         vert[ 8] = org2[2] - width * right2[2];
8188         vert[ 9] = org2[0] + width * right2[0];
8189         vert[10] = org2[1] + width * right2[1];
8190         vert[11] = org2[2] + width * right2[2];
8191 }
8192
8193 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)
8194 {
8195         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8196         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8197         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8198         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8199         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8200         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8201         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8202         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8203         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8204         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8205         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8206         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8207 }
8208
8209 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8210 {
8211         int i;
8212         float *vertex3f;
8213         float v[3];
8214         VectorSet(v, x, y, z);
8215         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8216                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8217                         break;
8218         if (i == mesh->numvertices)
8219         {
8220                 if (mesh->numvertices < mesh->maxvertices)
8221                 {
8222                         VectorCopy(v, vertex3f);
8223                         mesh->numvertices++;
8224                 }
8225                 return mesh->numvertices;
8226         }
8227         else
8228                 return i;
8229 }
8230
8231 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8232 {
8233         int i;
8234         int *e, element[3];
8235         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8236         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8237         e = mesh->element3i + mesh->numtriangles * 3;
8238         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8239         {
8240                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8241                 if (mesh->numtriangles < mesh->maxtriangles)
8242                 {
8243                         *e++ = element[0];
8244                         *e++ = element[1];
8245                         *e++ = element[2];
8246                         mesh->numtriangles++;
8247                 }
8248                 element[1] = element[2];
8249         }
8250 }
8251
8252 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8253 {
8254         int i;
8255         int *e, element[3];
8256         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8257         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8258         e = mesh->element3i + mesh->numtriangles * 3;
8259         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8260         {
8261                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8262                 if (mesh->numtriangles < mesh->maxtriangles)
8263                 {
8264                         *e++ = element[0];
8265                         *e++ = element[1];
8266                         *e++ = element[2];
8267                         mesh->numtriangles++;
8268                 }
8269                 element[1] = element[2];
8270         }
8271 }
8272
8273 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8274 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8275 {
8276         int planenum, planenum2;
8277         int w;
8278         int tempnumpoints;
8279         mplane_t *plane, *plane2;
8280         double maxdist;
8281         double temppoints[2][256*3];
8282         // figure out how large a bounding box we need to properly compute this brush
8283         maxdist = 0;
8284         for (w = 0;w < numplanes;w++)
8285                 maxdist = max(maxdist, fabs(planes[w].dist));
8286         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8287         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8288         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8289         {
8290                 w = 0;
8291                 tempnumpoints = 4;
8292                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8293                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8294                 {
8295                         if (planenum2 == planenum)
8296                                 continue;
8297                         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);
8298                         w = !w;
8299                 }
8300                 if (tempnumpoints < 3)
8301                         continue;
8302                 // generate elements forming a triangle fan for this polygon
8303                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8304         }
8305 }
8306
8307 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)
8308 {
8309         texturelayer_t *layer;
8310         layer = t->currentlayers + t->currentnumlayers++;
8311         layer->type = type;
8312         layer->depthmask = depthmask;
8313         layer->blendfunc1 = blendfunc1;
8314         layer->blendfunc2 = blendfunc2;
8315         layer->texture = texture;
8316         layer->texmatrix = *matrix;
8317         layer->color[0] = r;
8318         layer->color[1] = g;
8319         layer->color[2] = b;
8320         layer->color[3] = a;
8321 }
8322
8323 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8324 {
8325         double index, f;
8326         index = parms[2] + r_refdef.scene.time * parms[3];
8327         index -= floor(index);
8328         switch (func)
8329         {
8330         default:
8331         case Q3WAVEFUNC_NONE:
8332         case Q3WAVEFUNC_NOISE:
8333         case Q3WAVEFUNC_COUNT:
8334                 f = 0;
8335                 break;
8336         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8337         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8338         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8339         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8340         case Q3WAVEFUNC_TRIANGLE:
8341                 index *= 4;
8342                 f = index - floor(index);
8343                 if (index < 1)
8344                         f = f;
8345                 else if (index < 2)
8346                         f = 1 - f;
8347                 else if (index < 3)
8348                         f = -f;
8349                 else
8350                         f = -(1 - f);
8351                 break;
8352         }
8353         return (float)(parms[0] + parms[1] * f);
8354 }
8355
8356 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8357 {
8358         int w, h, idx;
8359         float f;
8360         float tcmat[12];
8361         matrix4x4_t matrix, temp;
8362         switch(tcmod->tcmod)
8363         {
8364                 case Q3TCMOD_COUNT:
8365                 case Q3TCMOD_NONE:
8366                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8367                                 matrix = r_waterscrollmatrix;
8368                         else
8369                                 matrix = identitymatrix;
8370                         break;
8371                 case Q3TCMOD_ENTITYTRANSLATE:
8372                         // this is used in Q3 to allow the gamecode to control texcoord
8373                         // scrolling on the entity, which is not supported in darkplaces yet.
8374                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8375                         break;
8376                 case Q3TCMOD_ROTATE:
8377                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8378                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8379                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8380                         break;
8381                 case Q3TCMOD_SCALE:
8382                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8383                         break;
8384                 case Q3TCMOD_SCROLL:
8385                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8386                         break;
8387                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8388                         w = (int) tcmod->parms[0];
8389                         h = (int) tcmod->parms[1];
8390                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8391                         f = f - floor(f);
8392                         idx = (int) floor(f * w * h);
8393                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8394                         break;
8395                 case Q3TCMOD_STRETCH:
8396                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8397                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8398                         break;
8399                 case Q3TCMOD_TRANSFORM:
8400                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8401                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8402                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8403                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8404                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8405                         break;
8406                 case Q3TCMOD_TURBULENT:
8407                         // this is handled in the RSurf_PrepareVertices function
8408                         matrix = identitymatrix;
8409                         break;
8410         }
8411         temp = *texmatrix;
8412         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8413 }
8414
8415 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8416 {
8417         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8418         char name[MAX_QPATH];
8419         skinframe_t *skinframe;
8420         unsigned char pixels[296*194];
8421         strlcpy(cache->name, skinname, sizeof(cache->name));
8422         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8423         if (developer_loading.integer)
8424                 Con_Printf("loading %s\n", name);
8425         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8426         if (!skinframe || !skinframe->base)
8427         {
8428                 unsigned char *f;
8429                 fs_offset_t filesize;
8430                 skinframe = NULL;
8431                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8432                 if (f)
8433                 {
8434                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8435                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8436                         Mem_Free(f);
8437                 }
8438         }
8439         cache->skinframe = skinframe;
8440 }
8441
8442 texture_t *R_GetCurrentTexture(texture_t *t)
8443 {
8444         int i;
8445         const entity_render_t *ent = rsurface.entity;
8446         dp_model_t *model = ent->model;
8447         q3shaderinfo_layer_tcmod_t *tcmod;
8448
8449         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
8450                 return t->currentframe;
8451         t->update_lastrenderframe = r_frame;
8452         t->update_lastrenderentity = (void *)ent;
8453
8454         // switch to an alternate material if this is a q1bsp animated material
8455         {
8456                 texture_t *texture = t;
8457                 int s = rsurface.ent_skinnum;
8458                 if ((unsigned int)s >= (unsigned int)model->numskins)
8459                         s = 0;
8460                 if (model->skinscenes)
8461                 {
8462                         if (model->skinscenes[s].framecount > 1)
8463                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8464                         else
8465                                 s = model->skinscenes[s].firstframe;
8466                 }
8467                 if (s > 0)
8468                         t = t + s * model->num_surfaces;
8469                 if (t->animated)
8470                 {
8471                         // use an alternate animation if the entity's frame is not 0,
8472                         // and only if the texture has an alternate animation
8473                         if (rsurface.ent_alttextures && t->anim_total[1])
8474                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8475                         else
8476                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8477                 }
8478                 texture->currentframe = t;
8479         }
8480
8481         // update currentskinframe to be a qw skin or animation frame
8482         if (rsurface.ent_qwskin >= 0)
8483         {
8484                 i = rsurface.ent_qwskin;
8485                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8486                 {
8487                         r_qwskincache_size = cl.maxclients;
8488                         if (r_qwskincache)
8489                                 Mem_Free(r_qwskincache);
8490                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8491                 }
8492                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8493                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8494                 t->currentskinframe = r_qwskincache[i].skinframe;
8495                 if (t->currentskinframe == NULL)
8496                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8497         }
8498         else if (t->numskinframes >= 2)
8499                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8500         if (t->backgroundnumskinframes >= 2)
8501                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8502
8503         t->currentmaterialflags = t->basematerialflags;
8504         t->currentalpha = rsurface.colormod[3];
8505         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8506                 t->currentalpha *= r_wateralpha.value;
8507         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8508                 t->currentalpha *= t->r_water_wateralpha;
8509         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8510                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8511         if (!(rsurface.ent_flags & RENDER_LIGHT))
8512                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8513         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8514         {
8515                 // pick a model lighting mode
8516                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8517                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8518                 else
8519                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8520         }
8521         if (rsurface.ent_flags & RENDER_ADDITIVE)
8522                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8523         else if (t->currentalpha < 1)
8524                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8525         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8526                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8527         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8528                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8529         if (t->backgroundnumskinframes)
8530                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8531         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8532         {
8533                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8534                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8535         }
8536         else
8537                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8538         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8539                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8540
8541         // there is no tcmod
8542         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8543         {
8544                 t->currenttexmatrix = r_waterscrollmatrix;
8545                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8546         }
8547         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8548         {
8549                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8550                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8551         }
8552
8553         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8554                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8555         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8556                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8557
8558         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8559         if (t->currentskinframe->qpixels)
8560                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8561         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8562         if (!t->basetexture)
8563                 t->basetexture = r_texture_notexture;
8564         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8565         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8566         t->nmaptexture = t->currentskinframe->nmap;
8567         if (!t->nmaptexture)
8568                 t->nmaptexture = r_texture_blanknormalmap;
8569         t->glosstexture = r_texture_black;
8570         t->glowtexture = t->currentskinframe->glow;
8571         t->fogtexture = t->currentskinframe->fog;
8572         if (t->backgroundnumskinframes)
8573         {
8574                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8575                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8576                 t->backgroundglosstexture = r_texture_black;
8577                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8578                 if (!t->backgroundnmaptexture)
8579                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8580         }
8581         else
8582         {
8583                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8584                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8585                 t->backgroundglosstexture = r_texture_black;
8586                 t->backgroundglowtexture = NULL;
8587         }
8588         t->specularpower = r_shadow_glossexponent.value;
8589         // TODO: store reference values for these in the texture?
8590         t->specularscale = 0;
8591         if (r_shadow_gloss.integer > 0)
8592         {
8593                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8594                 {
8595                         if (r_shadow_glossintensity.value > 0)
8596                         {
8597                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8598                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8599                                 t->specularscale = r_shadow_glossintensity.value;
8600                         }
8601                 }
8602                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8603                 {
8604                         t->glosstexture = r_texture_white;
8605                         t->backgroundglosstexture = r_texture_white;
8606                         t->specularscale = r_shadow_gloss2intensity.value;
8607                         t->specularpower = r_shadow_gloss2exponent.value;
8608                 }
8609         }
8610         t->specularscale *= t->specularscalemod;
8611         t->specularpower *= t->specularpowermod;
8612
8613         // lightmaps mode looks bad with dlights using actual texturing, so turn
8614         // off the colormap and glossmap, but leave the normalmap on as it still
8615         // accurately represents the shading involved
8616         if (gl_lightmaps.integer)
8617         {
8618                 t->basetexture = r_texture_grey128;
8619                 t->pantstexture = r_texture_black;
8620                 t->shirttexture = r_texture_black;
8621                 t->nmaptexture = r_texture_blanknormalmap;
8622                 t->glosstexture = r_texture_black;
8623                 t->glowtexture = NULL;
8624                 t->fogtexture = NULL;
8625                 t->backgroundbasetexture = NULL;
8626                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8627                 t->backgroundglosstexture = r_texture_black;
8628                 t->backgroundglowtexture = NULL;
8629                 t->specularscale = 0;
8630                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8631         }
8632
8633         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8634         VectorClear(t->dlightcolor);
8635         t->currentnumlayers = 0;
8636         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8637         {
8638                 int blendfunc1, blendfunc2;
8639                 qboolean depthmask;
8640                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8641                 {
8642                         blendfunc1 = GL_SRC_ALPHA;
8643                         blendfunc2 = GL_ONE;
8644                 }
8645                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8646                 {
8647                         blendfunc1 = GL_SRC_ALPHA;
8648                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8649                 }
8650                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8651                 {
8652                         blendfunc1 = t->customblendfunc[0];
8653                         blendfunc2 = t->customblendfunc[1];
8654                 }
8655                 else
8656                 {
8657                         blendfunc1 = GL_ONE;
8658                         blendfunc2 = GL_ZERO;
8659                 }
8660                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8661                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8662                 {
8663                         // fullbright is not affected by r_refdef.lightmapintensity
8664                         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]);
8665                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8666                                 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]);
8667                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8668                                 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]);
8669                 }
8670                 else
8671                 {
8672                         vec3_t ambientcolor;
8673                         float colorscale;
8674                         // set the color tint used for lights affecting this surface
8675                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8676                         colorscale = 2;
8677                         // q3bsp has no lightmap updates, so the lightstylevalue that
8678                         // would normally be baked into the lightmap must be
8679                         // applied to the color
8680                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8681                         if (model->type == mod_brushq3)
8682                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8683                         colorscale *= r_refdef.lightmapintensity;
8684                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8685                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8686                         // basic lit geometry
8687                         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]);
8688                         // add pants/shirt if needed
8689                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8690                                 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]);
8691                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8692                                 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]);
8693                         // now add ambient passes if needed
8694                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8695                         {
8696                                 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]);
8697                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8698                                         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]);
8699                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8700                                         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]);
8701                         }
8702                 }
8703                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8704                         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]);
8705                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8706                 {
8707                         // if this is opaque use alpha blend which will darken the earlier
8708                         // passes cheaply.
8709                         //
8710                         // if this is an alpha blended material, all the earlier passes
8711                         // were darkened by fog already, so we only need to add the fog
8712                         // color ontop through the fog mask texture
8713                         //
8714                         // if this is an additive blended material, all the earlier passes
8715                         // were darkened by fog already, and we should not add fog color
8716                         // (because the background was not darkened, there is no fog color
8717                         // that was lost behind it).
8718                         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]);
8719                 }
8720         }
8721
8722         return t->currentframe;
8723 }
8724
8725 rsurfacestate_t rsurface;
8726
8727 void R_Mesh_ResizeArrays(int newvertices)
8728 {
8729         float *base;
8730         if (rsurface.array_size >= newvertices)
8731                 return;
8732         if (rsurface.array_modelvertex3f)
8733                 Mem_Free(rsurface.array_modelvertex3f);
8734         rsurface.array_size = (newvertices + 1023) & ~1023;
8735         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8736         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8737         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8738         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8739         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8740         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8741         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8742         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8743         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8744         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8745         rsurface.array_color4f           = base + rsurface.array_size * 27;
8746         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8747 }
8748
8749 void RSurf_ActiveWorldEntity(void)
8750 {
8751         dp_model_t *model = r_refdef.scene.worldmodel;
8752         //if (rsurface.entity == r_refdef.scene.worldentity)
8753         //      return;
8754         rsurface.entity = r_refdef.scene.worldentity;
8755         rsurface.skeleton = NULL;
8756         rsurface.ent_skinnum = 0;
8757         rsurface.ent_qwskin = -1;
8758         rsurface.ent_shadertime = 0;
8759         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8760         if (rsurface.array_size < model->surfmesh.num_vertices)
8761                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8762         rsurface.matrix = identitymatrix;
8763         rsurface.inversematrix = identitymatrix;
8764         rsurface.matrixscale = 1;
8765         rsurface.inversematrixscale = 1;
8766         R_EntityMatrix(&identitymatrix);
8767         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8768         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8769         rsurface.fograngerecip = r_refdef.fograngerecip;
8770         rsurface.fogheightfade = r_refdef.fogheightfade;
8771         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8772         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8773         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8774         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8775         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8776         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8777         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8778         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8779         rsurface.colormod[3] = 1;
8780         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);
8781         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8782         rsurface.frameblend[0].lerp = 1;
8783         rsurface.ent_alttextures = false;
8784         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8785         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8786         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8787         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8788         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8789         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8790         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8791         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8792         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8793         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8794         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8795         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8796         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8797         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8798         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8799         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8800         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8801         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8802         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8803         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8804         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8805         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8806         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8807         rsurface.modelelement3i = model->surfmesh.data_element3i;
8808         rsurface.modelelement3s = model->surfmesh.data_element3s;
8809         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8810         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8811         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8812         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8813         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8814         rsurface.modelsurfaces = model->data_surfaces;
8815         rsurface.generatedvertex = false;
8816         rsurface.vertex3f  = rsurface.modelvertex3f;
8817         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8818         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8819         rsurface.svector3f = rsurface.modelsvector3f;
8820         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8821         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8822         rsurface.tvector3f = rsurface.modeltvector3f;
8823         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8824         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8825         rsurface.normal3f  = rsurface.modelnormal3f;
8826         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8827         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8828         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8829 }
8830
8831 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8832 {
8833         dp_model_t *model = ent->model;
8834         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8835         //      return;
8836         rsurface.entity = (entity_render_t *)ent;
8837         rsurface.skeleton = ent->skeleton;
8838         rsurface.ent_skinnum = ent->skinnum;
8839         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;
8840         rsurface.ent_shadertime = ent->shadertime;
8841         rsurface.ent_flags = ent->flags;
8842         if (rsurface.array_size < model->surfmesh.num_vertices)
8843                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8844         rsurface.matrix = ent->matrix;
8845         rsurface.inversematrix = ent->inversematrix;
8846         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8847         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8848         R_EntityMatrix(&rsurface.matrix);
8849         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8850         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8851         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8852         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8853         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8854         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8855         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8856         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8857         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8858         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8859         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8860         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8861         rsurface.colormod[3] = ent->alpha;
8862         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8863         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8864         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8865         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8866         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8867         if (ent->model->brush.submodel && !prepass)
8868         {
8869                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8870                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8871         }
8872         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8873         {
8874                 if (ent->animcache_vertex3f && !r_framedata_failed)
8875                 {
8876                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8877                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8878                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8879                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8880                 }
8881                 else if (wanttangents)
8882                 {
8883                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8884                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
8885                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
8886                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8887                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
8888                 }
8889                 else if (wantnormals)
8890                 {
8891                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8892                         rsurface.modelsvector3f = NULL;
8893                         rsurface.modeltvector3f = NULL;
8894                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8895                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
8896                 }
8897                 else
8898                 {
8899                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8900                         rsurface.modelsvector3f = NULL;
8901                         rsurface.modeltvector3f = NULL;
8902                         rsurface.modelnormal3f = NULL;
8903                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
8904                 }
8905                 rsurface.modelvertex3f_bufferobject = 0;
8906                 rsurface.modelvertex3f_bufferoffset = 0;
8907                 rsurface.modelsvector3f_bufferobject = 0;
8908                 rsurface.modelsvector3f_bufferoffset = 0;
8909                 rsurface.modeltvector3f_bufferobject = 0;
8910                 rsurface.modeltvector3f_bufferoffset = 0;
8911                 rsurface.modelnormal3f_bufferobject = 0;
8912                 rsurface.modelnormal3f_bufferoffset = 0;
8913                 rsurface.generatedvertex = true;
8914         }
8915         else
8916         {
8917                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8918                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8919                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8920                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8921                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8922                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8923                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8924                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8925                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8926                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8927                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8928                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8929                 rsurface.generatedvertex = false;
8930         }
8931         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8932         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8933         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8934         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8935         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8936         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8937         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8938         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8939         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8940         rsurface.modelelement3i = model->surfmesh.data_element3i;
8941         rsurface.modelelement3s = model->surfmesh.data_element3s;
8942         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8943         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8944         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8945         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8946         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8947         rsurface.modelsurfaces = model->data_surfaces;
8948         rsurface.vertex3f  = rsurface.modelvertex3f;
8949         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8950         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8951         rsurface.svector3f = rsurface.modelsvector3f;
8952         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8953         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8954         rsurface.tvector3f = rsurface.modeltvector3f;
8955         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8956         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8957         rsurface.normal3f  = rsurface.modelnormal3f;
8958         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8959         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8960         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8961 }
8962
8963 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)
8964 {
8965         rsurface.entity = r_refdef.scene.worldentity;
8966         rsurface.skeleton = NULL;
8967         rsurface.ent_skinnum = 0;
8968         rsurface.ent_qwskin = -1;
8969         rsurface.ent_shadertime = shadertime;
8970         rsurface.ent_flags = entflags;
8971         rsurface.modelnum_vertices = numvertices;
8972         rsurface.modelnum_triangles = numtriangles;
8973         if (rsurface.array_size < rsurface.modelnum_vertices)
8974                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
8975         rsurface.matrix = *matrix;
8976         rsurface.inversematrix = *inversematrix;
8977         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8978         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8979         R_EntityMatrix(&rsurface.matrix);
8980         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8981         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8982         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8983         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8984         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8985         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8986         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8987         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8988         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8989         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8990         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8991         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8992         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);
8993         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8994         rsurface.frameblend[0].lerp = 1;
8995         rsurface.ent_alttextures = false;
8996         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8997         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8998         if (wanttangents)
8999         {
9000                 rsurface.modelvertex3f = vertex3f;
9001                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9002                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9003                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9004         }
9005         else if (wantnormals)
9006         {
9007                 rsurface.modelvertex3f = vertex3f;
9008                 rsurface.modelsvector3f = NULL;
9009                 rsurface.modeltvector3f = NULL;
9010                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9011         }
9012         else
9013         {
9014                 rsurface.modelvertex3f = vertex3f;
9015                 rsurface.modelsvector3f = NULL;
9016                 rsurface.modeltvector3f = NULL;
9017                 rsurface.modelnormal3f = NULL;
9018         }
9019         rsurface.modelvertex3f_bufferobject = 0;
9020         rsurface.modelvertex3f_bufferoffset = 0;
9021         rsurface.modelsvector3f_bufferobject = 0;
9022         rsurface.modelsvector3f_bufferoffset = 0;
9023         rsurface.modeltvector3f_bufferobject = 0;
9024         rsurface.modeltvector3f_bufferoffset = 0;
9025         rsurface.modelnormal3f_bufferobject = 0;
9026         rsurface.modelnormal3f_bufferoffset = 0;
9027         rsurface.generatedvertex = true;
9028         rsurface.modellightmapcolor4f  = color4f;
9029         rsurface.modellightmapcolor4f_bufferobject = 0;
9030         rsurface.modellightmapcolor4f_bufferoffset = 0;
9031         rsurface.modeltexcoordtexture2f  = texcoord2f;
9032         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9033         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9034         rsurface.modeltexcoordlightmap2f  = NULL;
9035         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9036         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9037         rsurface.modelelement3i = element3i;
9038         rsurface.modelelement3s = element3s;
9039         rsurface.modelelement3i_bufferobject = 0;
9040         rsurface.modelelement3s_bufferobject = 0;
9041         rsurface.modellightmapoffsets = NULL;
9042         rsurface.modelsurfaces = NULL;
9043         rsurface.vertex3f  = rsurface.modelvertex3f;
9044         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9045         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9046         rsurface.svector3f = rsurface.modelsvector3f;
9047         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9048         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9049         rsurface.tvector3f = rsurface.modeltvector3f;
9050         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9051         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9052         rsurface.normal3f  = rsurface.modelnormal3f;
9053         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9054         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9055         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9056
9057         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9058         {
9059                 if ((wantnormals || wanttangents) && !normal3f)
9060                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9061                 if (wanttangents && !svector3f)
9062                         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);
9063         }
9064 }
9065
9066 float RSurf_FogPoint(const float *v)
9067 {
9068         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9069         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9070         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9071         float FogHeightFade = r_refdef.fogheightfade;
9072         float fogfrac;
9073         unsigned int fogmasktableindex;
9074         if (r_refdef.fogplaneviewabove)
9075                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9076         else
9077                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9078         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9079         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9080 }
9081
9082 float RSurf_FogVertex(const float *v)
9083 {
9084         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9085         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9086         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9087         float FogHeightFade = rsurface.fogheightfade;
9088         float fogfrac;
9089         unsigned int fogmasktableindex;
9090         if (r_refdef.fogplaneviewabove)
9091                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9092         else
9093                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9094         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9095         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9096 }
9097
9098 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9099 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9100 {
9101         int deformindex;
9102         int texturesurfaceindex;
9103         int i, j;
9104         float amplitude;
9105         float animpos;
9106         float scale;
9107         const float *v1, *in_tc;
9108         float *out_tc;
9109         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9110         float waveparms[4];
9111         q3shaderinfo_deform_t *deform;
9112         // 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
9113         if (rsurface.generatedvertex)
9114         {
9115                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9116                         generatenormals = true;
9117                 for (i = 0;i < Q3MAXDEFORMS;i++)
9118                 {
9119                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9120                         {
9121                                 generatetangents = true;
9122                                 generatenormals = true;
9123                         }
9124                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9125                                 generatenormals = true;
9126                 }
9127                 if (generatenormals && !rsurface.modelnormal3f)
9128                 {
9129                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9130                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9131                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9132                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9133                 }
9134                 if (generatetangents && !rsurface.modelsvector3f)
9135                 {
9136                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9137                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9138                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9139                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9140                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9141                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9142                         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);
9143                 }
9144         }
9145         rsurface.vertex3f  = rsurface.modelvertex3f;
9146         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9147         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9148         rsurface.svector3f = rsurface.modelsvector3f;
9149         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9150         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9151         rsurface.tvector3f = rsurface.modeltvector3f;
9152         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9153         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9154         rsurface.normal3f  = rsurface.modelnormal3f;
9155         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9156         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9157         // if vertices are deformed (sprite flares and things in maps, possibly
9158         // water waves, bulges and other deformations), generate them into
9159         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9160         // (may be static model data or generated data for an animated model, or
9161         //  the previous deform pass)
9162         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9163         {
9164                 switch (deform->deform)
9165                 {
9166                 default:
9167                 case Q3DEFORM_PROJECTIONSHADOW:
9168                 case Q3DEFORM_TEXT0:
9169                 case Q3DEFORM_TEXT1:
9170                 case Q3DEFORM_TEXT2:
9171                 case Q3DEFORM_TEXT3:
9172                 case Q3DEFORM_TEXT4:
9173                 case Q3DEFORM_TEXT5:
9174                 case Q3DEFORM_TEXT6:
9175                 case Q3DEFORM_TEXT7:
9176                 case Q3DEFORM_NONE:
9177                         break;
9178                 case Q3DEFORM_AUTOSPRITE:
9179                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9180                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9181                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9182                         VectorNormalize(newforward);
9183                         VectorNormalize(newright);
9184                         VectorNormalize(newup);
9185                         // make deformed versions of only the model vertices used by the specified surfaces
9186                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9187                         {
9188                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9189                                 // a single autosprite surface can contain multiple sprites...
9190                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9191                                 {
9192                                         VectorClear(center);
9193                                         for (i = 0;i < 4;i++)
9194                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9195                                         VectorScale(center, 0.25f, center);
9196                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9197                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9198                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9199                                         for (i = 0;i < 4;i++)
9200                                         {
9201                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9202                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9203                                         }
9204                                 }
9205                                 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);
9206                                 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);
9207                         }
9208                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9209                         rsurface.vertex3f_bufferobject = 0;
9210                         rsurface.vertex3f_bufferoffset = 0;
9211                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9212                         rsurface.svector3f_bufferobject = 0;
9213                         rsurface.svector3f_bufferoffset = 0;
9214                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9215                         rsurface.tvector3f_bufferobject = 0;
9216                         rsurface.tvector3f_bufferoffset = 0;
9217                         rsurface.normal3f = rsurface.array_deformednormal3f;
9218                         rsurface.normal3f_bufferobject = 0;
9219                         rsurface.normal3f_bufferoffset = 0;
9220                         break;
9221                 case Q3DEFORM_AUTOSPRITE2:
9222                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9223                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9224                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9225                         VectorNormalize(newforward);
9226                         VectorNormalize(newright);
9227                         VectorNormalize(newup);
9228                         // make deformed versions of only the model vertices used by the specified surfaces
9229                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9230                         {
9231                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9232                                 const float *v1, *v2;
9233                                 vec3_t start, end;
9234                                 float f, l;
9235                                 struct
9236                                 {
9237                                         float length2;
9238                                         const float *v1;
9239                                         const float *v2;
9240                                 }
9241                                 shortest[2];
9242                                 memset(shortest, 0, sizeof(shortest));
9243                                 // a single autosprite surface can contain multiple sprites...
9244                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9245                                 {
9246                                         VectorClear(center);
9247                                         for (i = 0;i < 4;i++)
9248                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9249                                         VectorScale(center, 0.25f, center);
9250                                         // find the two shortest edges, then use them to define the
9251                                         // axis vectors for rotating around the central axis
9252                                         for (i = 0;i < 6;i++)
9253                                         {
9254                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9255                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9256 #if 0
9257                                                 Debug_PolygonBegin(NULL, 0);
9258                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9259                                                 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);
9260                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9261                                                 Debug_PolygonEnd();
9262 #endif
9263                                                 l = VectorDistance2(v1, v2);
9264                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9265                                                 if (v1[2] != v2[2])
9266                                                         l += (1.0f / 1024.0f);
9267                                                 if (shortest[0].length2 > l || i == 0)
9268                                                 {
9269                                                         shortest[1] = shortest[0];
9270                                                         shortest[0].length2 = l;
9271                                                         shortest[0].v1 = v1;
9272                                                         shortest[0].v2 = v2;
9273                                                 }
9274                                                 else if (shortest[1].length2 > l || i == 1)
9275                                                 {
9276                                                         shortest[1].length2 = l;
9277                                                         shortest[1].v1 = v1;
9278                                                         shortest[1].v2 = v2;
9279                                                 }
9280                                         }
9281                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9282                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9283 #if 0
9284                                         Debug_PolygonBegin(NULL, 0);
9285                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9286                                         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);
9287                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9288                                         Debug_PolygonEnd();
9289 #endif
9290                                         // this calculates the right vector from the shortest edge
9291                                         // and the up vector from the edge midpoints
9292                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9293                                         VectorNormalize(right);
9294                                         VectorSubtract(end, start, up);
9295                                         VectorNormalize(up);
9296                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9297                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9298                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9299                                         VectorNegate(forward, forward);
9300                                         VectorReflect(forward, 0, up, forward);
9301                                         VectorNormalize(forward);
9302                                         CrossProduct(up, forward, newright);
9303                                         VectorNormalize(newright);
9304 #if 0
9305                                         Debug_PolygonBegin(NULL, 0);
9306                                         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);
9307                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9308                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9309                                         Debug_PolygonEnd();
9310 #endif
9311 #if 0
9312                                         Debug_PolygonBegin(NULL, 0);
9313                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9314                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9315                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9316                                         Debug_PolygonEnd();
9317 #endif
9318                                         // rotate the quad around the up axis vector, this is made
9319                                         // especially easy by the fact we know the quad is flat,
9320                                         // so we only have to subtract the center position and
9321                                         // measure distance along the right vector, and then
9322                                         // multiply that by the newright vector and add back the
9323                                         // center position
9324                                         // we also need to subtract the old position to undo the
9325                                         // displacement from the center, which we do with a
9326                                         // DotProduct, the subtraction/addition of center is also
9327                                         // optimized into DotProducts here
9328                                         l = DotProduct(right, center);
9329                                         for (i = 0;i < 4;i++)
9330                                         {
9331                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9332                                                 f = DotProduct(right, v1) - l;
9333                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9334                                         }
9335                                 }
9336                                 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);
9337                                 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);
9338                         }
9339                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9340                         rsurface.vertex3f_bufferobject = 0;
9341                         rsurface.vertex3f_bufferoffset = 0;
9342                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9343                         rsurface.svector3f_bufferobject = 0;
9344                         rsurface.svector3f_bufferoffset = 0;
9345                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9346                         rsurface.tvector3f_bufferobject = 0;
9347                         rsurface.tvector3f_bufferoffset = 0;
9348                         rsurface.normal3f = rsurface.array_deformednormal3f;
9349                         rsurface.normal3f_bufferobject = 0;
9350                         rsurface.normal3f_bufferoffset = 0;
9351                         break;
9352                 case Q3DEFORM_NORMAL:
9353                         // deform the normals to make reflections wavey
9354                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9355                         {
9356                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9357                                 for (j = 0;j < surface->num_vertices;j++)
9358                                 {
9359                                         float vertex[3];
9360                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9361                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9362                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9363                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9364                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9365                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9366                                         VectorNormalize(normal);
9367                                 }
9368                                 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);
9369                         }
9370                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9371                         rsurface.svector3f_bufferobject = 0;
9372                         rsurface.svector3f_bufferoffset = 0;
9373                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9374                         rsurface.tvector3f_bufferobject = 0;
9375                         rsurface.tvector3f_bufferoffset = 0;
9376                         rsurface.normal3f = rsurface.array_deformednormal3f;
9377                         rsurface.normal3f_bufferobject = 0;
9378                         rsurface.normal3f_bufferoffset = 0;
9379                         break;
9380                 case Q3DEFORM_WAVE:
9381                         // deform vertex array to make wavey water and flags and such
9382                         waveparms[0] = deform->waveparms[0];
9383                         waveparms[1] = deform->waveparms[1];
9384                         waveparms[2] = deform->waveparms[2];
9385                         waveparms[3] = deform->waveparms[3];
9386                         // this is how a divisor of vertex influence on deformation
9387                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9388                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9389                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9390                         {
9391                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9392                                 for (j = 0;j < surface->num_vertices;j++)
9393                                 {
9394                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9395                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9396                                         // if the wavefunc depends on time, evaluate it per-vertex
9397                                         if (waveparms[3])
9398                                         {
9399                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9400                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9401                                         }
9402                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9403                                 }
9404                         }
9405                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9406                         rsurface.vertex3f_bufferobject = 0;
9407                         rsurface.vertex3f_bufferoffset = 0;
9408                         break;
9409                 case Q3DEFORM_BULGE:
9410                         // deform vertex array to make the surface have moving bulges
9411                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9412                         {
9413                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9414                                 for (j = 0;j < surface->num_vertices;j++)
9415                                 {
9416                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9417                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9418                                 }
9419                         }
9420                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9421                         rsurface.vertex3f_bufferobject = 0;
9422                         rsurface.vertex3f_bufferoffset = 0;
9423                         break;
9424                 case Q3DEFORM_MOVE:
9425                         // deform vertex array
9426                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9427                         VectorScale(deform->parms, scale, waveparms);
9428                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9429                         {
9430                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9431                                 for (j = 0;j < surface->num_vertices;j++)
9432                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9433                         }
9434                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9435                         rsurface.vertex3f_bufferobject = 0;
9436                         rsurface.vertex3f_bufferoffset = 0;
9437                         break;
9438                 }
9439         }
9440         // generate texcoords based on the chosen texcoord source
9441         switch(rsurface.texture->tcgen.tcgen)
9442         {
9443         default:
9444         case Q3TCGEN_TEXTURE:
9445                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9446                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9447                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9448                 break;
9449         case Q3TCGEN_LIGHTMAP:
9450                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9451                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9452                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9453                 break;
9454         case Q3TCGEN_VECTOR:
9455                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9456                 {
9457                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9458                         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)
9459                         {
9460                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9461                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9462                         }
9463                 }
9464                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9465                 rsurface.texcoordtexture2f_bufferobject  = 0;
9466                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9467                 break;
9468         case Q3TCGEN_ENVIRONMENT:
9469                 // make environment reflections using a spheremap
9470                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9471                 {
9472                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9473                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9474                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9475                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9476                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9477                         {
9478                                 // identical to Q3A's method, but executed in worldspace so
9479                                 // carried models can be shiny too
9480
9481                                 float viewer[3], d, reflected[3], worldreflected[3];
9482
9483                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9484                                 // VectorNormalize(viewer);
9485
9486                                 d = DotProduct(normal, viewer);
9487
9488                                 reflected[0] = normal[0]*2*d - viewer[0];
9489                                 reflected[1] = normal[1]*2*d - viewer[1];
9490                                 reflected[2] = normal[2]*2*d - viewer[2];
9491                                 // note: this is proportinal to viewer, so we can normalize later
9492
9493                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9494                                 VectorNormalize(worldreflected);
9495
9496                                 // note: this sphere map only uses world x and z!
9497                                 // so positive and negative y will LOOK THE SAME.
9498                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9499                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9500                         }
9501                 }
9502                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9503                 rsurface.texcoordtexture2f_bufferobject  = 0;
9504                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9505                 break;
9506         }
9507         // the only tcmod that needs software vertex processing is turbulent, so
9508         // check for it here and apply the changes if needed
9509         // and we only support that as the first one
9510         // (handling a mixture of turbulent and other tcmods would be problematic
9511         //  without punting it entirely to a software path)
9512         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9513         {
9514                 amplitude = rsurface.texture->tcmods[0].parms[1];
9515                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9516                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9517                 {
9518                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9519                         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)
9520                         {
9521                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9522                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9523                         }
9524                 }
9525                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9526                 rsurface.texcoordtexture2f_bufferobject  = 0;
9527                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9528         }
9529         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9530         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9531         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9532         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9533 }
9534
9535 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9536 {
9537         int i, j;
9538         const msurface_t *surface = texturesurfacelist[0];
9539         const msurface_t *surface2;
9540         int firstvertex;
9541         int endvertex;
9542         int numvertices;
9543         int numtriangles;
9544         // TODO: lock all array ranges before render, rather than on each surface
9545         if (texturenumsurfaces == 1)
9546         {
9547                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9548                 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);
9549         }
9550         else if (r_batchmode.integer == 2)
9551         {
9552                 #define MAXBATCHTRIANGLES 4096
9553                 int batchtriangles = 0;
9554                 static int batchelements[MAXBATCHTRIANGLES*3];
9555                 for (i = 0;i < texturenumsurfaces;i = j)
9556                 {
9557                         surface = texturesurfacelist[i];
9558                         j = i + 1;
9559                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9560                         {
9561                                 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);
9562                                 continue;
9563                         }
9564                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9565                         batchtriangles = surface->num_triangles;
9566                         firstvertex = surface->num_firstvertex;
9567                         endvertex = surface->num_firstvertex + surface->num_vertices;
9568                         for (;j < texturenumsurfaces;j++)
9569                         {
9570                                 surface2 = texturesurfacelist[j];
9571                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9572                                         break;
9573                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9574                                 batchtriangles += surface2->num_triangles;
9575                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9576                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9577                         }
9578                         surface2 = texturesurfacelist[j-1];
9579                         numvertices = endvertex - firstvertex;
9580                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9581                 }
9582         }
9583         else if (r_batchmode.integer == 1)
9584         {
9585                 for (i = 0;i < texturenumsurfaces;i = j)
9586                 {
9587                         surface = texturesurfacelist[i];
9588                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9589                                 if (texturesurfacelist[j] != surface2)
9590                                         break;
9591                         surface2 = texturesurfacelist[j-1];
9592                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9593                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9594                         GL_LockArrays(surface->num_firstvertex, numvertices);
9595                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9596                 }
9597         }
9598         else
9599         {
9600                 for (i = 0;i < texturenumsurfaces;i++)
9601                 {
9602                         surface = texturesurfacelist[i];
9603                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9604                         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);
9605                 }
9606         }
9607 }
9608
9609 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9610 {
9611         switch(vid.renderpath)
9612         {
9613         case RENDERPATH_CGGL:
9614 #ifdef SUPPORTCG
9615                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9616                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9617 #endif
9618                 break;
9619         case RENDERPATH_GL20:
9620                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9621                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9622                 break;
9623         case RENDERPATH_GL13:
9624         case RENDERPATH_GL11:
9625                 R_Mesh_TexBind(0, surface->lightmaptexture);
9626                 break;
9627         }
9628 }
9629
9630 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9631 {
9632         // pick the closest matching water plane and bind textures
9633         int planeindex, vertexindex;
9634         float d, bestd;
9635         vec3_t vert;
9636         const float *v;
9637         r_waterstate_waterplane_t *p, *bestp;
9638         bestd = 0;
9639         bestp = NULL;
9640         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9641         {
9642                 d = 0;
9643                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9644                 {
9645                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9646                         d += fabs(PlaneDiff(vert, &p->plane));
9647                 }
9648                 if (bestd > d || !bestp)
9649                 {
9650                         bestd = d;
9651                         bestp = p;
9652                 }
9653         }
9654         switch(vid.renderpath)
9655         {
9656         case RENDERPATH_CGGL:
9657 #ifdef SUPPORTCG
9658                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9659                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9660 #endif
9661                 break;
9662         case RENDERPATH_GL20:
9663                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9664                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9665                 break;
9666         case RENDERPATH_GL13:
9667         case RENDERPATH_GL11:
9668                 break;
9669         }
9670 }
9671
9672 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9673 {
9674         int i;
9675         const msurface_t *surface;
9676         if (r_waterstate.renderingscene)
9677                 return;
9678         for (i = 0;i < texturenumsurfaces;i++)
9679         {
9680                 surface = texturesurfacelist[i];
9681                 RSurf_BindLightmapForSurface(surface);
9682                 RSurf_BindReflectionForSurface(surface);
9683                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9684                 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);
9685         }
9686 }
9687
9688 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9689 {
9690         int i;
9691         int j;
9692         const msurface_t *surface = texturesurfacelist[0];
9693         const msurface_t *surface2;
9694         int firstvertex;
9695         int endvertex;
9696         int numvertices;
9697         int numtriangles;
9698         if (texturenumsurfaces == 1)
9699         {
9700                 RSurf_BindLightmapForSurface(surface);
9701                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9702                 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);
9703         }
9704         else if (r_batchmode.integer == 2)
9705         {
9706 #define MAXBATCHTRIANGLES 4096
9707                 int batchtriangles = 0;
9708                 static int batchelements[MAXBATCHTRIANGLES*3];
9709                 for (i = 0;i < texturenumsurfaces;i = j)
9710                 {
9711                         surface = texturesurfacelist[i];
9712                         RSurf_BindLightmapForSurface(surface);
9713                         j = i + 1;
9714                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9715                         {
9716                                 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);
9717                                 continue;
9718                         }
9719                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9720                         batchtriangles = surface->num_triangles;
9721                         firstvertex = surface->num_firstvertex;
9722                         endvertex = surface->num_firstvertex + surface->num_vertices;
9723                         for (;j < texturenumsurfaces;j++)
9724                         {
9725                                 surface2 = texturesurfacelist[j];
9726                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9727                                         break;
9728                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9729                                 batchtriangles += surface2->num_triangles;
9730                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9731                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9732                         }
9733                         surface2 = texturesurfacelist[j-1];
9734                         numvertices = endvertex - firstvertex;
9735                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9736                 }
9737         }
9738         else if (r_batchmode.integer == 1)
9739         {
9740 #if 0
9741                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9742                 for (i = 0;i < texturenumsurfaces;i = j)
9743                 {
9744                         surface = texturesurfacelist[i];
9745                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9746                                 if (texturesurfacelist[j] != surface2)
9747                                         break;
9748                         Con_Printf(" %i", j - i);
9749                 }
9750                 Con_Printf("\n");
9751                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9752 #endif
9753                 for (i = 0;i < texturenumsurfaces;i = j)
9754                 {
9755                         surface = texturesurfacelist[i];
9756                         RSurf_BindLightmapForSurface(surface);
9757                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9758                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9759                                         break;
9760 #if 0
9761                         Con_Printf(" %i", j - i);
9762 #endif
9763                         surface2 = texturesurfacelist[j-1];
9764                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9765                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9766                         GL_LockArrays(surface->num_firstvertex, numvertices);
9767                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9768                 }
9769 #if 0
9770                 Con_Printf("\n");
9771 #endif
9772         }
9773         else
9774         {
9775                 for (i = 0;i < texturenumsurfaces;i++)
9776                 {
9777                         surface = texturesurfacelist[i];
9778                         RSurf_BindLightmapForSurface(surface);
9779                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9780                         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);
9781                 }
9782         }
9783 }
9784
9785 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9786 {
9787         int j;
9788         int texturesurfaceindex;
9789         if (r_showsurfaces.integer == 2)
9790         {
9791                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9792                 {
9793                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9794                         for (j = 0;j < surface->num_triangles;j++)
9795                         {
9796                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9797                                 GL_Color(f, f, f, 1);
9798                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9799                         }
9800                 }
9801         }
9802         else
9803         {
9804                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9805                 {
9806                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9807                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9808                         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);
9809                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9810                         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);
9811                 }
9812         }
9813 }
9814
9815 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9816 {
9817         int texturesurfaceindex;
9818         int i;
9819         const float *v;
9820         float *c2;
9821         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9822         {
9823                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9824                 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)
9825                 {
9826                         c2[0] = 0.5;
9827                         c2[1] = 0.5;
9828                         c2[2] = 0.5;
9829                         c2[3] = 1;
9830                 }
9831         }
9832         rsurface.lightmapcolor4f = rsurface.array_color4f;
9833         rsurface.lightmapcolor4f_bufferobject = 0;
9834         rsurface.lightmapcolor4f_bufferoffset = 0;
9835 }
9836
9837 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9838 {
9839         int texturesurfaceindex;
9840         int i;
9841         float f;
9842         const float *v;
9843         const float *c;
9844         float *c2;
9845         if (rsurface.lightmapcolor4f)
9846         {
9847                 // generate color arrays for the surfaces in this list
9848                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9849                 {
9850                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9851                         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)
9852                         {
9853                                 f = RSurf_FogVertex(v);
9854                                 c2[0] = c[0] * f;
9855                                 c2[1] = c[1] * f;
9856                                 c2[2] = c[2] * f;
9857                                 c2[3] = c[3];
9858                         }
9859                 }
9860         }
9861         else
9862         {
9863                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9864                 {
9865                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9866                         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)
9867                         {
9868                                 f = RSurf_FogVertex(v);
9869                                 c2[0] = f;
9870                                 c2[1] = f;
9871                                 c2[2] = f;
9872                                 c2[3] = 1;
9873                         }
9874                 }
9875         }
9876         rsurface.lightmapcolor4f = rsurface.array_color4f;
9877         rsurface.lightmapcolor4f_bufferobject = 0;
9878         rsurface.lightmapcolor4f_bufferoffset = 0;
9879 }
9880
9881 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9882 {
9883         int texturesurfaceindex;
9884         int i;
9885         float f;
9886         const float *v;
9887         const float *c;
9888         float *c2;
9889         if (!rsurface.lightmapcolor4f)
9890                 return;
9891         // generate color arrays for the surfaces in this list
9892         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9893         {
9894                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9895                 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)
9896                 {
9897                         f = RSurf_FogVertex(v);
9898                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9899                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9900                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9901                         c2[3] = c[3];
9902                 }
9903         }
9904         rsurface.lightmapcolor4f = rsurface.array_color4f;
9905         rsurface.lightmapcolor4f_bufferobject = 0;
9906         rsurface.lightmapcolor4f_bufferoffset = 0;
9907 }
9908
9909 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
9910 {
9911         int texturesurfaceindex;
9912         int i;
9913         const float *c;
9914         float *c2;
9915         if (!rsurface.lightmapcolor4f)
9916                 return;
9917         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9918         {
9919                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9920                 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)
9921                 {
9922                         c2[0] = c[0] * r;
9923                         c2[1] = c[1] * g;
9924                         c2[2] = c[2] * b;
9925                         c2[3] = c[3] * a;
9926                 }
9927         }
9928         rsurface.lightmapcolor4f = rsurface.array_color4f;
9929         rsurface.lightmapcolor4f_bufferobject = 0;
9930         rsurface.lightmapcolor4f_bufferoffset = 0;
9931 }
9932
9933 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9934 {
9935         int texturesurfaceindex;
9936         int i;
9937         const float *c;
9938         float *c2;
9939         if (!rsurface.lightmapcolor4f)
9940                 return;
9941         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9942         {
9943                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9944                 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)
9945                 {
9946                         c2[0] = c[0] + r_refdef.scene.ambient;
9947                         c2[1] = c[1] + r_refdef.scene.ambient;
9948                         c2[2] = c[2] + r_refdef.scene.ambient;
9949                         c2[3] = c[3];
9950                 }
9951         }
9952         rsurface.lightmapcolor4f = rsurface.array_color4f;
9953         rsurface.lightmapcolor4f_bufferobject = 0;
9954         rsurface.lightmapcolor4f_bufferoffset = 0;
9955 }
9956
9957 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9958 {
9959         // TODO: optimize
9960         rsurface.lightmapcolor4f = NULL;
9961         rsurface.lightmapcolor4f_bufferobject = 0;
9962         rsurface.lightmapcolor4f_bufferoffset = 0;
9963         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9964         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9965         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9966         GL_Color(r, g, b, a);
9967         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
9968 }
9969
9970 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9971 {
9972         // TODO: optimize applyfog && applycolor case
9973         // just apply fog if necessary, and tint the fog color array if necessary
9974         rsurface.lightmapcolor4f = NULL;
9975         rsurface.lightmapcolor4f_bufferobject = 0;
9976         rsurface.lightmapcolor4f_bufferoffset = 0;
9977         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9978         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9979         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9980         GL_Color(r, g, b, a);
9981         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9982 }
9983
9984 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9985 {
9986         int texturesurfaceindex;
9987         int i;
9988         float *c;
9989         // TODO: optimize
9990         if (texturesurfacelist[0]->lightmapinfo)
9991         {
9992                 // generate color arrays for the surfaces in this list
9993                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9994                 {
9995                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9996                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
9997                         {
9998                                 if (surface->lightmapinfo->samples)
9999                                 {
10000                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10001                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10002                                         VectorScale(lm, scale, c);
10003                                         if (surface->lightmapinfo->styles[1] != 255)
10004                                         {
10005                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10006                                                 lm += size3;
10007                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10008                                                 VectorMA(c, scale, lm, c);
10009                                                 if (surface->lightmapinfo->styles[2] != 255)
10010                                                 {
10011                                                         lm += size3;
10012                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10013                                                         VectorMA(c, scale, lm, c);
10014                                                         if (surface->lightmapinfo->styles[3] != 255)
10015                                                         {
10016                                                                 lm += size3;
10017                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10018                                                                 VectorMA(c, scale, lm, c);
10019                                                         }
10020                                                 }
10021                                         }
10022                                 }
10023                                 else
10024                                         VectorClear(c);
10025                                 c[3] = 1;
10026                         }
10027                 }
10028                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10029                 rsurface.lightmapcolor4f_bufferobject = 0;
10030                 rsurface.lightmapcolor4f_bufferoffset = 0;
10031         }
10032         else
10033         {
10034                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10035                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10036                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10037         }
10038         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10039         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10040         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10041         GL_Color(r, g, b, a);
10042         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10043 }
10044
10045 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10046 {
10047         int texturesurfaceindex;
10048         int i;
10049         float f;
10050         float alpha;
10051         const float *v;
10052         const float *n;
10053         float *c;
10054         vec3_t ambientcolor;
10055         vec3_t diffusecolor;
10056         vec3_t lightdir;
10057         // TODO: optimize
10058         // model lighting
10059         VectorCopy(rsurface.modellight_lightdir, lightdir);
10060         f = 0.5f * r_refdef.lightmapintensity;
10061         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10062         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10063         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10064         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10065         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10066         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10067         alpha = *a;
10068         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10069         {
10070                 // generate color arrays for the surfaces in this list
10071                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10072                 {
10073                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10074                         int numverts = surface->num_vertices;
10075                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10076                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10077                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10078                         // q3-style directional shading
10079                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10080                         {
10081                                 if ((f = DotProduct(n, lightdir)) > 0)
10082                                         VectorMA(ambientcolor, f, diffusecolor, c);
10083                                 else
10084                                         VectorCopy(ambientcolor, c);
10085                                 c[3] = alpha;
10086                         }
10087                 }
10088                 *r = 1;
10089                 *g = 1;
10090                 *b = 1;
10091                 *a = 1;
10092                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10093                 rsurface.lightmapcolor4f_bufferobject = 0;
10094                 rsurface.lightmapcolor4f_bufferoffset = 0;
10095                 *applycolor = false;
10096         }
10097         else
10098         {
10099                 *r = ambientcolor[0];
10100                 *g = ambientcolor[1];
10101                 *b = ambientcolor[2];
10102                 rsurface.lightmapcolor4f = NULL;
10103                 rsurface.lightmapcolor4f_bufferobject = 0;
10104                 rsurface.lightmapcolor4f_bufferoffset = 0;
10105         }
10106 }
10107
10108 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10109 {
10110         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10111         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10112         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10113         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10114         GL_Color(r, g, b, a);
10115         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10116 }
10117
10118 void RSurf_SetupDepthAndCulling(void)
10119 {
10120         // submodels are biased to avoid z-fighting with world surfaces that they
10121         // may be exactly overlapping (avoids z-fighting artifacts on certain
10122         // doors and things in Quake maps)
10123         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10124         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10125         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10126         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10127 }
10128
10129 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10130 {
10131         // transparent sky would be ridiculous
10132         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10133                 return;
10134         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10135         skyrenderlater = true;
10136         RSurf_SetupDepthAndCulling();
10137         GL_DepthMask(true);
10138         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10139         // skymasking on them, and Quake3 never did sky masking (unlike
10140         // software Quake and software Quake2), so disable the sky masking
10141         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10142         // and skymasking also looks very bad when noclipping outside the
10143         // level, so don't use it then either.
10144         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10145         {
10146                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10147                 R_Mesh_ColorPointer(NULL, 0, 0);
10148                 R_Mesh_ResetTextureState();
10149                 if (skyrendermasked)
10150                 {
10151                         R_SetupShader_DepthOrShadow();
10152                         // depth-only (masking)
10153                         GL_ColorMask(0,0,0,0);
10154                         // just to make sure that braindead drivers don't draw
10155                         // anything despite that colormask...
10156                         GL_BlendFunc(GL_ZERO, GL_ONE);
10157                 }
10158                 else
10159                 {
10160                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10161                         // fog sky
10162                         GL_BlendFunc(GL_ONE, GL_ZERO);
10163                 }
10164                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10165                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10166                 if (skyrendermasked)
10167                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10168         }
10169         R_Mesh_ResetTextureState();
10170         GL_Color(1, 1, 1, 1);
10171 }
10172
10173 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10174 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10175 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10176 {
10177         qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
10178         qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
10179
10180         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10181                 return;
10182
10183         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10184                 R_Mesh_ColorPointer(NULL, 0, 0);
10185         else
10186                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10187
10188         if (refract)
10189         {
10190                 // render background
10191                 GL_BlendFunc(GL_ONE, GL_ZERO);
10192                 GL_DepthMask(true);
10193                 GL_AlphaTest(false);
10194
10195                 GL_Color(1, 1, 1, 1);
10196                 R_Mesh_ColorPointer(NULL, 0, 0);
10197
10198                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10199                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10200                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10201                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10202                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10203                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10204                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10205                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10206                 GL_LockArrays(0, 0);
10207
10208                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10209                 GL_DepthMask(false);
10210                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10211                         R_Mesh_ColorPointer(NULL, 0, 0);
10212                 else
10213                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10214         }
10215
10216         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10217
10218         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10219         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10220         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10221         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10222         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10223         if (!prepass)
10224                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10225
10226         if (refract)
10227                 GL_DepthMask(true);
10228         else
10229                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10230         GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10231         GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
10232
10233         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10234         {
10235                 if (refract || reflect)
10236                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10237                 else
10238                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10239         }
10240         else
10241         {
10242                 if (refract || reflect)
10243                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10244                 else
10245                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10246         }
10247         GL_LockArrays(0, 0);
10248 }
10249
10250 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10251 {
10252         // OpenGL 1.3 path - anything not completely ancient
10253         int texturesurfaceindex;
10254         qboolean applycolor;
10255         qboolean applyfog;
10256         int layerindex;
10257         const texturelayer_t *layer;
10258         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10259
10260         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10261         {
10262                 vec4_t layercolor;
10263                 int layertexrgbscale;
10264                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10265                 {
10266                         if (layerindex == 0)
10267                                 GL_AlphaTest(true);
10268                         else
10269                         {
10270                                 GL_AlphaTest(false);
10271                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10272                         }
10273                 }
10274                 GL_DepthMask(layer->depthmask && writedepth);
10275                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10276                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10277                 {
10278                         layertexrgbscale = 4;
10279                         VectorScale(layer->color, 0.25f, layercolor);
10280                 }
10281                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10282                 {
10283                         layertexrgbscale = 2;
10284                         VectorScale(layer->color, 0.5f, layercolor);
10285                 }
10286                 else
10287                 {
10288                         layertexrgbscale = 1;
10289                         VectorScale(layer->color, 1.0f, layercolor);
10290                 }
10291                 layercolor[3] = layer->color[3];
10292                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10293                 R_Mesh_ColorPointer(NULL, 0, 0);
10294                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10295                 switch (layer->type)
10296                 {
10297                 case TEXTURELAYERTYPE_LITTEXTURE:
10298                         // single-pass lightmapped texture with 2x rgbscale
10299                         R_Mesh_TexBind(0, r_texture_white);
10300                         R_Mesh_TexMatrix(0, NULL);
10301                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10302                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10303                         R_Mesh_TexBind(1, layer->texture);
10304                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10305                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10306                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10307                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10308                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10309                         else if (rsurface.uselightmaptexture)
10310                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10311                         else
10312                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10313                         break;
10314                 case TEXTURELAYERTYPE_TEXTURE:
10315                         // singletexture unlit texture with transparency support
10316                         R_Mesh_TexBind(0, layer->texture);
10317                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10318                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10319                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10320                         R_Mesh_TexBind(1, 0);
10321                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10322                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10323                         break;
10324                 case TEXTURELAYERTYPE_FOG:
10325                         // singletexture fogging
10326                         if (layer->texture)
10327                         {
10328                                 R_Mesh_TexBind(0, layer->texture);
10329                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10330                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10331                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10332                         }
10333                         else
10334                         {
10335                                 R_Mesh_TexBind(0, 0);
10336                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10337                         }
10338                         R_Mesh_TexBind(1, 0);
10339                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10340                         // generate a color array for the fog pass
10341                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10342                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10343                         {
10344                                 int i;
10345                                 float f;
10346                                 const float *v;
10347                                 float *c;
10348                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10349                                 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)
10350                                 {
10351                                         f = 1 - RSurf_FogVertex(v);
10352                                         c[0] = layercolor[0];
10353                                         c[1] = layercolor[1];
10354                                         c[2] = layercolor[2];
10355                                         c[3] = f * layercolor[3];
10356                                 }
10357                         }
10358                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10359                         break;
10360                 default:
10361                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10362                 }
10363                 GL_LockArrays(0, 0);
10364         }
10365         CHECKGLERROR
10366         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10367         {
10368                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10369                 GL_AlphaTest(false);
10370         }
10371 }
10372
10373 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10374 {
10375         // OpenGL 1.1 - crusty old voodoo path
10376         int texturesurfaceindex;
10377         qboolean applyfog;
10378         int layerindex;
10379         const texturelayer_t *layer;
10380         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10381
10382         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10383         {
10384                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10385                 {
10386                         if (layerindex == 0)
10387                                 GL_AlphaTest(true);
10388                         else
10389                         {
10390                                 GL_AlphaTest(false);
10391                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10392                         }
10393                 }
10394                 GL_DepthMask(layer->depthmask && writedepth);
10395                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10396                 R_Mesh_ColorPointer(NULL, 0, 0);
10397                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10398                 switch (layer->type)
10399                 {
10400                 case TEXTURELAYERTYPE_LITTEXTURE:
10401                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10402                         {
10403                                 // two-pass lit texture with 2x rgbscale
10404                                 // first the lightmap pass
10405                                 R_Mesh_TexBind(0, r_texture_white);
10406                                 R_Mesh_TexMatrix(0, NULL);
10407                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10408                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10409                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10410                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10411                                 else if (rsurface.uselightmaptexture)
10412                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10413                                 else
10414                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10415                                 GL_LockArrays(0, 0);
10416                                 // then apply the texture to it
10417                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10418                                 R_Mesh_TexBind(0, layer->texture);
10419                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10420                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10421                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10422                                 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);
10423                         }
10424                         else
10425                         {
10426                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10427                                 R_Mesh_TexBind(0, layer->texture);
10428                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10429                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10430                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10431                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10432                                         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);
10433                                 else
10434                                         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);
10435                         }
10436                         break;
10437                 case TEXTURELAYERTYPE_TEXTURE:
10438                         // singletexture unlit texture with transparency support
10439                         R_Mesh_TexBind(0, layer->texture);
10440                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10441                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10442                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10443                         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);
10444                         break;
10445                 case TEXTURELAYERTYPE_FOG:
10446                         // singletexture fogging
10447                         if (layer->texture)
10448                         {
10449                                 R_Mesh_TexBind(0, layer->texture);
10450                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10451                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10452                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10453                         }
10454                         else
10455                         {
10456                                 R_Mesh_TexBind(0, 0);
10457                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10458                         }
10459                         // generate a color array for the fog pass
10460                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10461                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10462                         {
10463                                 int i;
10464                                 float f;
10465                                 const float *v;
10466                                 float *c;
10467                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10468                                 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)
10469                                 {
10470                                         f = 1 - RSurf_FogVertex(v);
10471                                         c[0] = layer->color[0];
10472                                         c[1] = layer->color[1];
10473                                         c[2] = layer->color[2];
10474                                         c[3] = f * layer->color[3];
10475                                 }
10476                         }
10477                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10478                         break;
10479                 default:
10480                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10481                 }
10482                 GL_LockArrays(0, 0);
10483         }
10484         CHECKGLERROR
10485         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10486         {
10487                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10488                 GL_AlphaTest(false);
10489         }
10490 }
10491
10492 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10493 {
10494         float c[4];
10495
10496         GL_AlphaTest(false);
10497         R_Mesh_ColorPointer(NULL, 0, 0);
10498         R_Mesh_ResetTextureState();
10499         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10500
10501         if(rsurface.texture && rsurface.texture->currentskinframe)
10502         {
10503                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10504                 c[3] *= rsurface.texture->currentalpha;
10505         }
10506         else
10507         {
10508                 c[0] = 1;
10509                 c[1] = 0;
10510                 c[2] = 1;
10511                 c[3] = 1;
10512         }
10513
10514         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10515         {
10516                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10517                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10518                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10519         }
10520
10521         // brighten it up (as texture value 127 means "unlit")
10522         c[0] *= 2 * r_refdef.view.colorscale;
10523         c[1] *= 2 * r_refdef.view.colorscale;
10524         c[2] *= 2 * r_refdef.view.colorscale;
10525
10526         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10527                 c[3] *= r_wateralpha.value;
10528
10529         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10530         {
10531                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10532                 GL_DepthMask(false);
10533         }
10534         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10535         {
10536                 GL_BlendFunc(GL_ONE, GL_ONE);
10537                 GL_DepthMask(false);
10538         }
10539         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10540         {
10541                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10542                 GL_DepthMask(false);
10543         }
10544         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10545         {
10546                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10547                 GL_DepthMask(false);
10548         }
10549         else
10550         {
10551                 GL_BlendFunc(GL_ONE, GL_ZERO);
10552                 GL_DepthMask(writedepth);
10553         }
10554
10555         rsurface.lightmapcolor4f = NULL;
10556
10557         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10558         {
10559                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10560
10561                 rsurface.lightmapcolor4f = NULL;
10562                 rsurface.lightmapcolor4f_bufferobject = 0;
10563                 rsurface.lightmapcolor4f_bufferoffset = 0;
10564         }
10565         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10566         {
10567                 qboolean applycolor = true;
10568                 float one = 1.0;
10569
10570                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10571
10572                 r_refdef.lightmapintensity = 1;
10573                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10574                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10575         }
10576         else
10577         {
10578                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10579
10580                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10581                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10582                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10583         }
10584
10585         if(!rsurface.lightmapcolor4f)
10586                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10587
10588         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10589         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10590         if(r_refdef.fogenabled)
10591                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10592
10593         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10594         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10595 }
10596
10597 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10598 {
10599         CHECKGLERROR
10600         RSurf_SetupDepthAndCulling();
10601         if (r_showsurfaces.integer == 3 && !prepass)
10602         {
10603                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10604                 return;
10605         }
10606         switch (vid.renderpath)
10607         {
10608         case RENDERPATH_GL20:
10609         case RENDERPATH_CGGL:
10610                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10611                 break;
10612         case RENDERPATH_GL13:
10613                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10614                 break;
10615         case RENDERPATH_GL11:
10616                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10617                 break;
10618         }
10619         CHECKGLERROR
10620 }
10621
10622 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10623 {
10624         CHECKGLERROR
10625         RSurf_SetupDepthAndCulling();
10626         if (r_showsurfaces.integer == 3 && !prepass)
10627         {
10628                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10629                 return;
10630         }
10631         switch (vid.renderpath)
10632         {
10633         case RENDERPATH_GL20:
10634         case RENDERPATH_CGGL:
10635                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10636                 break;
10637         case RENDERPATH_GL13:
10638                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10639                 break;
10640         case RENDERPATH_GL11:
10641                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10642                 break;
10643         }
10644         CHECKGLERROR
10645 }
10646
10647 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10648 {
10649         int i, j;
10650         int texturenumsurfaces, endsurface;
10651         texture_t *texture;
10652         const msurface_t *surface;
10653         const msurface_t *texturesurfacelist[256];
10654
10655         // if the model is static it doesn't matter what value we give for
10656         // wantnormals and wanttangents, so this logic uses only rules applicable
10657         // to a model, knowing that they are meaningless otherwise
10658         if (ent == r_refdef.scene.worldentity)
10659                 RSurf_ActiveWorldEntity();
10660         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10661                 RSurf_ActiveModelEntity(ent, false, false, false);
10662         else
10663         {
10664                 switch (vid.renderpath)
10665                 {
10666                 case RENDERPATH_GL20:
10667                 case RENDERPATH_CGGL:
10668                         RSurf_ActiveModelEntity(ent, true, true, false);
10669                         break;
10670                 case RENDERPATH_GL13:
10671                 case RENDERPATH_GL11:
10672                         RSurf_ActiveModelEntity(ent, true, false, false);
10673                         break;
10674                 }
10675         }
10676
10677         if (r_transparentdepthmasking.integer)
10678         {
10679                 qboolean setup = false;
10680                 for (i = 0;i < numsurfaces;i = j)
10681                 {
10682                         j = i + 1;
10683                         surface = rsurface.modelsurfaces + surfacelist[i];
10684                         texture = surface->texture;
10685                         rsurface.texture = R_GetCurrentTexture(texture);
10686                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10687                         // scan ahead until we find a different texture
10688                         endsurface = min(i + 1024, numsurfaces);
10689                         texturenumsurfaces = 0;
10690                         texturesurfacelist[texturenumsurfaces++] = surface;
10691                         for (;j < endsurface;j++)
10692                         {
10693                                 surface = rsurface.modelsurfaces + surfacelist[j];
10694                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10695                                         break;
10696                                 texturesurfacelist[texturenumsurfaces++] = surface;
10697                         }
10698                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10699                                 continue;
10700                         // render the range of surfaces as depth
10701                         if (!setup)
10702                         {
10703                                 setup = true;
10704                                 GL_ColorMask(0,0,0,0);
10705                                 GL_Color(1,1,1,1);
10706                                 GL_DepthTest(true);
10707                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10708                                 GL_DepthMask(true);
10709                                 GL_AlphaTest(false);
10710                                 R_Mesh_ColorPointer(NULL, 0, 0);
10711                                 R_Mesh_ResetTextureState();
10712                                 R_SetupShader_DepthOrShadow();
10713                         }
10714                         RSurf_SetupDepthAndCulling();
10715                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10716                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10717                 }
10718                 if (setup)
10719                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10720         }
10721
10722         for (i = 0;i < numsurfaces;i = j)
10723         {
10724                 j = i + 1;
10725                 surface = rsurface.modelsurfaces + surfacelist[i];
10726                 texture = surface->texture;
10727                 rsurface.texture = R_GetCurrentTexture(texture);
10728                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10729                 // scan ahead until we find a different texture
10730                 endsurface = min(i + 1024, numsurfaces);
10731                 texturenumsurfaces = 0;
10732                 texturesurfacelist[texturenumsurfaces++] = surface;
10733                 for (;j < endsurface;j++)
10734                 {
10735                         surface = rsurface.modelsurfaces + surfacelist[j];
10736                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10737                                 break;
10738                         texturesurfacelist[texturenumsurfaces++] = surface;
10739                 }
10740                 // render the range of surfaces
10741                 if (ent == r_refdef.scene.worldentity)
10742                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10743                 else
10744                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10745         }
10746         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10747         GL_AlphaTest(false);
10748 }
10749
10750 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10751 {
10752         // transparent surfaces get pushed off into the transparent queue
10753         int surfacelistindex;
10754         const msurface_t *surface;
10755         vec3_t tempcenter, center;
10756         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10757         {
10758                 surface = texturesurfacelist[surfacelistindex];
10759                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10760                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10761                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10762                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10763                 if (queueentity->transparent_offset) // transparent offset
10764                 {
10765                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10766                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10767                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10768                 }
10769                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10770         }
10771 }
10772
10773 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10774 {
10775         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10776         CHECKGLERROR
10777         if (depthonly)
10778         {
10779                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10780                         return;
10781                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10782                         return;
10783                 RSurf_SetupDepthAndCulling();
10784                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10785                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10786         }
10787         else if (prepass)
10788         {
10789                 if (!rsurface.texture->currentnumlayers)
10790                         return;
10791                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10792                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10793                 else
10794                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10795         }
10796         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10797         {
10798                 RSurf_SetupDepthAndCulling();
10799                 GL_AlphaTest(false);
10800                 R_Mesh_ColorPointer(NULL, 0, 0);
10801                 R_Mesh_ResetTextureState();
10802                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10803                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10804                 GL_DepthMask(true);
10805                 GL_BlendFunc(GL_ONE, GL_ZERO);
10806                 GL_Color(0, 0, 0, 1);
10807                 GL_DepthTest(writedepth);
10808                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10809         }
10810         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10811         {
10812                 RSurf_SetupDepthAndCulling();
10813                 GL_AlphaTest(false);
10814                 R_Mesh_ColorPointer(NULL, 0, 0);
10815                 R_Mesh_ResetTextureState();
10816                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10817                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10818                 GL_DepthMask(true);
10819                 GL_BlendFunc(GL_ONE, GL_ZERO);
10820                 GL_DepthTest(true);
10821                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10822         }
10823         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10824                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10825         else if (!rsurface.texture->currentnumlayers)
10826                 return;
10827         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10828         {
10829                 // in the deferred case, transparent surfaces were queued during prepass
10830                 if (!r_shadow_usingdeferredprepass)
10831                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10832         }
10833         else
10834         {
10835                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10836                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10837         }
10838         CHECKGLERROR
10839 }
10840
10841 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10842 {
10843         int i, j;
10844         texture_t *texture;
10845         // break the surface list down into batches by texture and use of lightmapping
10846         for (i = 0;i < numsurfaces;i = j)
10847         {
10848                 j = i + 1;
10849                 // texture is the base texture pointer, rsurface.texture is the
10850                 // current frame/skin the texture is directing us to use (for example
10851                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10852                 // use skin 1 instead)
10853                 texture = surfacelist[i]->texture;
10854                 rsurface.texture = R_GetCurrentTexture(texture);
10855                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10856                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10857                 {
10858                         // if this texture is not the kind we want, skip ahead to the next one
10859                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10860                                 ;
10861                         continue;
10862                 }
10863                 // simply scan ahead until we find a different texture or lightmap state
10864                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10865                         ;
10866                 // render the range of surfaces
10867                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10868         }
10869 }
10870
10871 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10872 {
10873         CHECKGLERROR
10874         if (depthonly)
10875         {
10876                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10877                         return;
10878                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10879                         return;
10880                 RSurf_SetupDepthAndCulling();
10881                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10882                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10883         }
10884         else if (prepass)
10885         {
10886                 if (!rsurface.texture->currentnumlayers)
10887                         return;
10888                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10889                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10890                 else
10891                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10892         }
10893         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10894         {
10895                 RSurf_SetupDepthAndCulling();
10896                 GL_AlphaTest(false);
10897                 R_Mesh_ColorPointer(NULL, 0, 0);
10898                 R_Mesh_ResetTextureState();
10899                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10900                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10901                 GL_DepthMask(true);
10902                 GL_BlendFunc(GL_ONE, GL_ZERO);
10903                 GL_Color(0, 0, 0, 1);
10904                 GL_DepthTest(writedepth);
10905                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10906         }
10907         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10908         {
10909                 RSurf_SetupDepthAndCulling();
10910                 GL_AlphaTest(false);
10911                 R_Mesh_ColorPointer(NULL, 0, 0);
10912                 R_Mesh_ResetTextureState();
10913                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10914                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10915                 GL_DepthMask(true);
10916                 GL_BlendFunc(GL_ONE, GL_ZERO);
10917                 GL_DepthTest(true);
10918                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10919         }
10920         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10921                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10922         else if (!rsurface.texture->currentnumlayers)
10923                 return;
10924         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10925         {
10926                 // in the deferred case, transparent surfaces were queued during prepass
10927                 if (!r_shadow_usingdeferredprepass)
10928                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10929         }
10930         else
10931         {
10932                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10933                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10934         }
10935         CHECKGLERROR
10936 }
10937
10938 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10939 {
10940         int i, j;
10941         texture_t *texture;
10942         // break the surface list down into batches by texture and use of lightmapping
10943         for (i = 0;i < numsurfaces;i = j)
10944         {
10945                 j = i + 1;
10946                 // texture is the base texture pointer, rsurface.texture is the
10947                 // current frame/skin the texture is directing us to use (for example
10948                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10949                 // use skin 1 instead)
10950                 texture = surfacelist[i]->texture;
10951                 rsurface.texture = R_GetCurrentTexture(texture);
10952                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10953                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10954                 {
10955                         // if this texture is not the kind we want, skip ahead to the next one
10956                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10957                                 ;
10958                         continue;
10959                 }
10960                 // simply scan ahead until we find a different texture or lightmap state
10961                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10962                         ;
10963                 // render the range of surfaces
10964                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10965         }
10966 }
10967
10968 float locboxvertex3f[6*4*3] =
10969 {
10970         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10971         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10972         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10973         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10974         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10975         1,0,0, 0,0,0, 0,1,0, 1,1,0
10976 };
10977
10978 unsigned short locboxelements[6*2*3] =
10979 {
10980          0, 1, 2, 0, 2, 3,
10981          4, 5, 6, 4, 6, 7,
10982          8, 9,10, 8,10,11,
10983         12,13,14, 12,14,15,
10984         16,17,18, 16,18,19,
10985         20,21,22, 20,22,23
10986 };
10987
10988 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10989 {
10990         int i, j;
10991         cl_locnode_t *loc = (cl_locnode_t *)ent;
10992         vec3_t mins, size;
10993         float vertex3f[6*4*3];
10994         CHECKGLERROR
10995         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10996         GL_DepthMask(false);
10997         GL_DepthRange(0, 1);
10998         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10999         GL_DepthTest(true);
11000         GL_CullFace(GL_NONE);
11001         R_EntityMatrix(&identitymatrix);
11002
11003         R_Mesh_VertexPointer(vertex3f, 0, 0);
11004         R_Mesh_ColorPointer(NULL, 0, 0);
11005         R_Mesh_ResetTextureState();
11006         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11007
11008         i = surfacelist[0];
11009         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11010                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11011                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11012                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11013
11014         if (VectorCompare(loc->mins, loc->maxs))
11015         {
11016                 VectorSet(size, 2, 2, 2);
11017                 VectorMA(loc->mins, -0.5f, size, mins);
11018         }
11019         else
11020         {
11021                 VectorCopy(loc->mins, mins);
11022                 VectorSubtract(loc->maxs, loc->mins, size);
11023         }
11024
11025         for (i = 0;i < 6*4*3;)
11026                 for (j = 0;j < 3;j++, i++)
11027                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11028
11029         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11030 }
11031
11032 void R_DrawLocs(void)
11033 {
11034         int index;
11035         cl_locnode_t *loc, *nearestloc;
11036         vec3_t center;
11037         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11038         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11039         {
11040                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11041                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11042         }
11043 }
11044
11045 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11046 {
11047         if (decalsystem->decals)
11048                 Mem_Free(decalsystem->decals);
11049         memset(decalsystem, 0, sizeof(*decalsystem));
11050 }
11051
11052 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)
11053 {
11054         tridecal_t *decal;
11055         tridecal_t *decals;
11056         int i;
11057         int maxdecals;
11058
11059         // expand or initialize the system
11060         if (decalsystem->maxdecals <= decalsystem->numdecals)
11061         {
11062                 decalsystem_t old = *decalsystem;
11063                 qboolean useshortelements;
11064                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11065                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11066                 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)));
11067                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11068                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11069                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11070                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11071                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11072                 if (decalsystem->numdecals)
11073                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11074                 if (old.decals)
11075                         Mem_Free(old.decals);
11076                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11077                         decalsystem->element3i[i] = i;
11078                 if (useshortelements)
11079                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11080                                 decalsystem->element3s[i] = i;
11081         }
11082
11083         // grab a decal and search for another free slot for the next one
11084         maxdecals = decalsystem->maxdecals;
11085         decals = decalsystem->decals;
11086         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11087         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11088                 ;
11089         decalsystem->freedecal = i;
11090         if (decalsystem->numdecals <= i)
11091                 decalsystem->numdecals = i + 1;
11092
11093         // initialize the decal
11094         decal->lived = 0;
11095         decal->triangleindex = triangleindex;
11096         decal->surfaceindex = surfaceindex;
11097         decal->decalsequence = decalsequence;
11098         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11099         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11100         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11101         decal->color4ub[0][3] = 255;
11102         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11103         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11104         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11105         decal->color4ub[1][3] = 255;
11106         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11107         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11108         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11109         decal->color4ub[2][3] = 255;
11110         decal->vertex3f[0][0] = v0[0];
11111         decal->vertex3f[0][1] = v0[1];
11112         decal->vertex3f[0][2] = v0[2];
11113         decal->vertex3f[1][0] = v1[0];
11114         decal->vertex3f[1][1] = v1[1];
11115         decal->vertex3f[1][2] = v1[2];
11116         decal->vertex3f[2][0] = v2[0];
11117         decal->vertex3f[2][1] = v2[1];
11118         decal->vertex3f[2][2] = v2[2];
11119         decal->texcoord2f[0][0] = t0[0];
11120         decal->texcoord2f[0][1] = t0[1];
11121         decal->texcoord2f[1][0] = t1[0];
11122         decal->texcoord2f[1][1] = t1[1];
11123         decal->texcoord2f[2][0] = t2[0];
11124         decal->texcoord2f[2][1] = t2[1];
11125 }
11126
11127 extern cvar_t cl_decals_bias;
11128 extern cvar_t cl_decals_models;
11129 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11130 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)
11131 {
11132         matrix4x4_t projection;
11133         decalsystem_t *decalsystem;
11134         qboolean dynamic;
11135         dp_model_t *model;
11136         const float *vertex3f;
11137         const msurface_t *surface;
11138         const msurface_t *surfaces;
11139         const int *surfacelist;
11140         const texture_t *texture;
11141         int numvertices;
11142         int numtriangles;
11143         int numsurfacelist;
11144         int surfacelistindex;
11145         int surfaceindex;
11146         int triangleindex;
11147         int decalsurfaceindex;
11148         int cornerindex;
11149         int index;
11150         int numpoints;
11151         const int *e;
11152         float localorigin[3];
11153         float localnormal[3];
11154         float localmins[3];
11155         float localmaxs[3];
11156         float localsize;
11157         float ilocalsize;
11158         float v[9][3];
11159         float tc[9][2];
11160         float c[9][4];
11161         //float normal[3];
11162         float planes[6][4];
11163         float f;
11164         float points[2][9][3];
11165         float angles[3];
11166         float temp[3];
11167
11168         decalsystem = &ent->decalsystem;
11169         model = ent->model;
11170         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11171         {
11172                 R_DecalSystem_Reset(&ent->decalsystem);
11173                 return;
11174         }
11175
11176         if (!model->brush.data_nodes && !cl_decals_models.integer)
11177         {
11178                 if (decalsystem->model)
11179                         R_DecalSystem_Reset(decalsystem);
11180                 return;
11181         }
11182
11183         if (decalsystem->model != model)
11184                 R_DecalSystem_Reset(decalsystem);
11185         decalsystem->model = model;
11186
11187         RSurf_ActiveModelEntity(ent, false, false, false);
11188
11189         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11190         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11191         VectorNormalize(localnormal);
11192         localsize = worldsize*rsurface.inversematrixscale;
11193         ilocalsize = 1.0f / localsize;
11194         localmins[0] = localorigin[0] - localsize;
11195         localmins[1] = localorigin[1] - localsize;
11196         localmins[2] = localorigin[2] - localsize;
11197         localmaxs[0] = localorigin[0] + localsize;
11198         localmaxs[1] = localorigin[1] + localsize;
11199         localmaxs[2] = localorigin[2] + localsize;
11200
11201         //VectorCopy(localnormal, planes[4]);
11202         //VectorVectors(planes[4], planes[2], planes[0]);
11203         AnglesFromVectors(angles, localnormal, NULL, false);
11204         AngleVectors(angles, planes[0], planes[2], planes[4]);
11205         VectorNegate(planes[0], planes[1]);
11206         VectorNegate(planes[2], planes[3]);
11207         VectorNegate(planes[4], planes[5]);
11208         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11209         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11210         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11211         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11212         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11213         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11214
11215 #if 1
11216 // works
11217 {
11218         matrix4x4_t forwardprojection;
11219         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11220         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11221 }
11222 #else
11223 // broken
11224 {
11225         float projectionvector[4][3];
11226         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11227         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11228         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11229         projectionvector[0][0] = planes[0][0] * ilocalsize;
11230         projectionvector[0][1] = planes[1][0] * ilocalsize;
11231         projectionvector[0][2] = planes[2][0] * ilocalsize;
11232         projectionvector[1][0] = planes[0][1] * ilocalsize;
11233         projectionvector[1][1] = planes[1][1] * ilocalsize;
11234         projectionvector[1][2] = planes[2][1] * ilocalsize;
11235         projectionvector[2][0] = planes[0][2] * ilocalsize;
11236         projectionvector[2][1] = planes[1][2] * ilocalsize;
11237         projectionvector[2][2] = planes[2][2] * ilocalsize;
11238         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11239         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11240         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11241         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11242 }
11243 #endif
11244
11245         dynamic = model->surfmesh.isanimated;
11246         vertex3f = rsurface.modelvertex3f;
11247         numsurfacelist = model->nummodelsurfaces;
11248         surfacelist = model->sortedmodelsurfaces;
11249         surfaces = model->data_surfaces;
11250         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11251         {
11252                 surfaceindex = surfacelist[surfacelistindex];
11253                 surface = surfaces + surfaceindex;
11254                 // skip transparent surfaces
11255                 texture = surface->texture;
11256                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11257                         continue;
11258                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11259                         continue;
11260                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11261                         continue;
11262                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11263                 numvertices = surface->num_vertices;
11264                 numtriangles = surface->num_triangles;
11265                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11266                 {
11267                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11268                         {
11269                                 index = 3*e[cornerindex];
11270                                 VectorCopy(vertex3f + index, v[cornerindex]);
11271                         }
11272                         // cull backfaces
11273                         //TriangleNormal(v[0], v[1], v[2], normal);
11274                         //if (DotProduct(normal, localnormal) < 0.0f)
11275                         //      continue;
11276                         // clip by each of the box planes formed from the projection matrix
11277                         // if anything survives, we emit the decal
11278                         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]);
11279                         if (numpoints < 3)
11280                                 continue;
11281                         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]);
11282                         if (numpoints < 3)
11283                                 continue;
11284                         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]);
11285                         if (numpoints < 3)
11286                                 continue;
11287                         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]);
11288                         if (numpoints < 3)
11289                                 continue;
11290                         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]);
11291                         if (numpoints < 3)
11292                                 continue;
11293                         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]);
11294                         if (numpoints < 3)
11295                                 continue;
11296                         // some part of the triangle survived, so we have to accept it...
11297                         if (dynamic)
11298                         {
11299                                 // dynamic always uses the original triangle
11300                                 numpoints = 3;
11301                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11302                                 {
11303                                         index = 3*e[cornerindex];
11304                                         VectorCopy(vertex3f + index, v[cornerindex]);
11305                                 }
11306                         }
11307                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11308                         {
11309                                 // convert vertex positions to texcoords
11310                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11311                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11312                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11313                                 // calculate distance fade from the projection origin
11314                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11315                                 f = bound(0.0f, f, 1.0f);
11316                                 c[cornerindex][0] = r * f;
11317                                 c[cornerindex][1] = g * f;
11318                                 c[cornerindex][2] = b * f;
11319                                 c[cornerindex][3] = 1.0f;
11320                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11321                         }
11322                         if (dynamic)
11323                                 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);
11324                         else
11325                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11326                                         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);
11327                 }
11328         }
11329 }
11330
11331 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11332 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)
11333 {
11334         int renderentityindex;
11335         float worldmins[3];
11336         float worldmaxs[3];
11337         entity_render_t *ent;
11338
11339         if (!cl_decals_newsystem.integer)
11340                 return;
11341
11342         worldmins[0] = worldorigin[0] - worldsize;
11343         worldmins[1] = worldorigin[1] - worldsize;
11344         worldmins[2] = worldorigin[2] - worldsize;
11345         worldmaxs[0] = worldorigin[0] + worldsize;
11346         worldmaxs[1] = worldorigin[1] + worldsize;
11347         worldmaxs[2] = worldorigin[2] + worldsize;
11348
11349         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11350
11351         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11352         {
11353                 ent = r_refdef.scene.entities[renderentityindex];
11354                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11355                         continue;
11356
11357                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11358         }
11359 }
11360
11361 typedef struct r_decalsystem_splatqueue_s
11362 {
11363         vec3_t worldorigin;
11364         vec3_t worldnormal;
11365         float color[4];
11366         float tcrange[4];
11367         float worldsize;
11368         int decalsequence;
11369 }
11370 r_decalsystem_splatqueue_t;
11371
11372 int r_decalsystem_numqueued = 0;
11373 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11374
11375 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)
11376 {
11377         r_decalsystem_splatqueue_t *queue;
11378
11379         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11380                 return;
11381
11382         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11383         VectorCopy(worldorigin, queue->worldorigin);
11384         VectorCopy(worldnormal, queue->worldnormal);
11385         Vector4Set(queue->color, r, g, b, a);
11386         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11387         queue->worldsize = worldsize;
11388         queue->decalsequence = cl.decalsequence++;
11389 }
11390
11391 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11392 {
11393         int i;
11394         r_decalsystem_splatqueue_t *queue;
11395
11396         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11397                 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);
11398         r_decalsystem_numqueued = 0;
11399 }
11400
11401 extern cvar_t cl_decals_max;
11402 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11403 {
11404         int i;
11405         decalsystem_t *decalsystem = &ent->decalsystem;
11406         int numdecals;
11407         int killsequence;
11408         tridecal_t *decal;
11409         float frametime;
11410         float lifetime;
11411
11412         if (!decalsystem->numdecals)
11413                 return;
11414
11415         if (r_showsurfaces.integer)
11416                 return;
11417
11418         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11419         {
11420                 R_DecalSystem_Reset(decalsystem);
11421                 return;
11422         }
11423
11424         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11425         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11426
11427         if (decalsystem->lastupdatetime)
11428                 frametime = (cl.time - decalsystem->lastupdatetime);
11429         else
11430                 frametime = 0;
11431         decalsystem->lastupdatetime = cl.time;
11432         decal = decalsystem->decals;
11433         numdecals = decalsystem->numdecals;
11434
11435         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11436         {
11437                 if (decal->color4ub[0][3])
11438                 {
11439                         decal->lived += frametime;
11440                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11441                         {
11442                                 memset(decal, 0, sizeof(*decal));
11443                                 if (decalsystem->freedecal > i)
11444                                         decalsystem->freedecal = i;
11445                         }
11446                 }
11447         }
11448         decal = decalsystem->decals;
11449         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11450                 numdecals--;
11451
11452         // collapse the array by shuffling the tail decals into the gaps
11453         for (;;)
11454         {
11455                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11456                         decalsystem->freedecal++;
11457                 if (decalsystem->freedecal == numdecals)
11458                         break;
11459                 decal[decalsystem->freedecal] = decal[--numdecals];
11460         }
11461
11462         decalsystem->numdecals = numdecals;
11463
11464         if (numdecals <= 0)
11465         {
11466                 // if there are no decals left, reset decalsystem
11467                 R_DecalSystem_Reset(decalsystem);
11468         }
11469 }
11470
11471 extern skinframe_t *decalskinframe;
11472 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11473 {
11474         int i;
11475         decalsystem_t *decalsystem = &ent->decalsystem;
11476         int numdecals;
11477         tridecal_t *decal;
11478         float fadedelay;
11479         float faderate;
11480         float alpha;
11481         float *v3f;
11482         float *c4f;
11483         float *t2f;
11484         const int *e;
11485         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11486         int numtris = 0;
11487
11488         numdecals = decalsystem->numdecals;
11489         if (!numdecals)
11490                 return;
11491
11492         if (r_showsurfaces.integer)
11493                 return;
11494
11495         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11496         {
11497                 R_DecalSystem_Reset(decalsystem);
11498                 return;
11499         }
11500
11501         // if the model is static it doesn't matter what value we give for
11502         // wantnormals and wanttangents, so this logic uses only rules applicable
11503         // to a model, knowing that they are meaningless otherwise
11504         if (ent == r_refdef.scene.worldentity)
11505                 RSurf_ActiveWorldEntity();
11506         else
11507                 RSurf_ActiveModelEntity(ent, false, false, false);
11508
11509         decalsystem->lastupdatetime = cl.time;
11510         decal = decalsystem->decals;
11511
11512         fadedelay = cl_decals_time.value;
11513         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11514
11515         // update vertex positions for animated models
11516         v3f = decalsystem->vertex3f;
11517         c4f = decalsystem->color4f;
11518         t2f = decalsystem->texcoord2f;
11519         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11520         {
11521                 if (!decal->color4ub[0][3])
11522                         continue;
11523
11524                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11525                         continue;
11526
11527                 // update color values for fading decals
11528                 if (decal->lived >= cl_decals_time.value)
11529                 {
11530                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11531                         alpha *= (1.0f/255.0f);
11532                 }
11533                 else
11534                         alpha = 1.0f/255.0f;
11535
11536                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11537                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11538                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11539                 c4f[ 3] = 1;
11540                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11541                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11542                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11543                 c4f[ 7] = 1;
11544                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11545                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11546                 c4f[10] = decal->color4ub[2][2] * alpha;
11547                 c4f[11] = 1;
11548
11549                 t2f[0] = decal->texcoord2f[0][0];
11550                 t2f[1] = decal->texcoord2f[0][1];
11551                 t2f[2] = decal->texcoord2f[1][0];
11552                 t2f[3] = decal->texcoord2f[1][1];
11553                 t2f[4] = decal->texcoord2f[2][0];
11554                 t2f[5] = decal->texcoord2f[2][1];
11555
11556                 // update vertex positions for animated models
11557                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11558                 {
11559                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11560                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11561                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11562                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11563                 }
11564                 else
11565                 {
11566                         VectorCopy(decal->vertex3f[0], v3f);
11567                         VectorCopy(decal->vertex3f[1], v3f + 3);
11568                         VectorCopy(decal->vertex3f[2], v3f + 6);
11569                 }
11570
11571                 v3f += 9;
11572                 c4f += 12;
11573                 t2f += 6;
11574                 numtris++;
11575         }
11576
11577         if (numtris > 0)
11578         {
11579                 r_refdef.stats.drawndecals += numtris;
11580
11581                 if (r_refdef.fogenabled)
11582                 {
11583                         switch(vid.renderpath)
11584                         {
11585                         case RENDERPATH_GL20:
11586                         case RENDERPATH_CGGL:
11587                         case RENDERPATH_GL13:
11588                         case RENDERPATH_GL11:
11589                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11590                                 {
11591                                         alpha = RSurf_FogVertex(v3f);
11592                                         c4f[0] *= alpha;
11593                                         c4f[1] *= alpha;
11594                                         c4f[2] *= alpha;
11595                                 }
11596                                 break;
11597                         }
11598                 }
11599
11600                 // now render the decals all at once
11601                 // (this assumes they all use one particle font texture!)
11602                 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);
11603                 R_Mesh_ResetTextureState();
11604                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11605                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11606                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11607                 GL_DepthMask(false);
11608                 GL_DepthRange(0, 1);
11609                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11610                 GL_DepthTest(true);
11611                 GL_CullFace(GL_NONE);
11612                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11613                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11614                 GL_LockArrays(0, numtris * 3);
11615                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11616                 GL_LockArrays(0, 0);
11617         }
11618 }
11619
11620 static void R_DrawModelDecals(void)
11621 {
11622         int i, numdecals;
11623
11624         // fade faster when there are too many decals
11625         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11626         for (i = 0;i < r_refdef.scene.numentities;i++)
11627                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11628
11629         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11630         for (i = 0;i < r_refdef.scene.numentities;i++)
11631                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11632                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11633
11634         R_DecalSystem_ApplySplatEntitiesQueue();
11635
11636         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11637         for (i = 0;i < r_refdef.scene.numentities;i++)
11638                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11639
11640         r_refdef.stats.totaldecals += numdecals;
11641
11642         if (r_showsurfaces.integer)
11643                 return;
11644
11645         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11646
11647         for (i = 0;i < r_refdef.scene.numentities;i++)
11648         {
11649                 if (!r_refdef.viewcache.entityvisible[i])
11650                         continue;
11651                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11652                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11653         }
11654 }
11655
11656 void R_DrawDebugModel(void)
11657 {
11658         entity_render_t *ent = rsurface.entity;
11659         int i, j, k, l, flagsmask;
11660         const int *elements;
11661         q3mbrush_t *brush;
11662         const msurface_t *surface;
11663         dp_model_t *model = ent->model;
11664         vec3_t v;
11665
11666         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11667
11668         R_Mesh_ColorPointer(NULL, 0, 0);
11669         R_Mesh_ResetTextureState();
11670         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11671         GL_DepthRange(0, 1);
11672         GL_DepthTest(!r_showdisabledepthtest.integer);
11673         GL_DepthMask(false);
11674         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11675
11676         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11677         {
11678                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11679                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11680                 {
11681                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11682                         {
11683                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11684                                 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);
11685                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11686                         }
11687                 }
11688                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11689                 {
11690                         if (surface->num_collisiontriangles)
11691                         {
11692                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11693                                 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);
11694                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11695                         }
11696                 }
11697         }
11698
11699         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11700
11701         if (r_showtris.integer || r_shownormals.integer)
11702         {
11703                 if (r_showdisabledepthtest.integer)
11704                 {
11705                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11706                         GL_DepthMask(false);
11707                 }
11708                 else
11709                 {
11710                         GL_BlendFunc(GL_ONE, GL_ZERO);
11711                         GL_DepthMask(true);
11712                 }
11713                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11714                 {
11715                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11716                                 continue;
11717                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11718                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11719                         {
11720                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11721                                 if (r_showtris.value > 0)
11722                                 {
11723                                         if (!rsurface.texture->currentlayers->depthmask)
11724                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11725                                         else if (ent == r_refdef.scene.worldentity)
11726                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11727                                         else
11728                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11729                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11730                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11731                                         R_Mesh_ColorPointer(NULL, 0, 0);
11732                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11733                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11734                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11735                                         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);
11736                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11737                                         CHECKGLERROR
11738                                 }
11739                                 if (r_shownormals.value < 0)
11740                                 {
11741                                         qglBegin(GL_LINES);
11742                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11743                                         {
11744                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11745                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11746                                                 qglVertex3f(v[0], v[1], v[2]);
11747                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11748                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11749                                                 qglVertex3f(v[0], v[1], v[2]);
11750                                         }
11751                                         qglEnd();
11752                                         CHECKGLERROR
11753                                 }
11754                                 if (r_shownormals.value > 0)
11755                                 {
11756                                         qglBegin(GL_LINES);
11757                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11758                                         {
11759                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11760                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11761                                                 qglVertex3f(v[0], v[1], v[2]);
11762                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11763                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11764                                                 qglVertex3f(v[0], v[1], v[2]);
11765                                         }
11766                                         qglEnd();
11767                                         CHECKGLERROR
11768                                         qglBegin(GL_LINES);
11769                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11770                                         {
11771                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11772                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11773                                                 qglVertex3f(v[0], v[1], v[2]);
11774                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11775                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11776                                                 qglVertex3f(v[0], v[1], v[2]);
11777                                         }
11778                                         qglEnd();
11779                                         CHECKGLERROR
11780                                         qglBegin(GL_LINES);
11781                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11782                                         {
11783                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11784                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11785                                                 qglVertex3f(v[0], v[1], v[2]);
11786                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11787                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11788                                                 qglVertex3f(v[0], v[1], v[2]);
11789                                         }
11790                                         qglEnd();
11791                                         CHECKGLERROR
11792                                 }
11793                         }
11794                 }
11795                 rsurface.texture = NULL;
11796         }
11797 }
11798
11799 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11800 int r_maxsurfacelist = 0;
11801 const msurface_t **r_surfacelist = NULL;
11802 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11803 {
11804         int i, j, endj, f, flagsmask;
11805         texture_t *t;
11806         dp_model_t *model = r_refdef.scene.worldmodel;
11807         msurface_t *surfaces;
11808         unsigned char *update;
11809         int numsurfacelist = 0;
11810         if (model == NULL)
11811                 return;
11812
11813         if (r_maxsurfacelist < model->num_surfaces)
11814         {
11815                 r_maxsurfacelist = model->num_surfaces;
11816                 if (r_surfacelist)
11817                         Mem_Free((msurface_t**)r_surfacelist);
11818                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11819         }
11820
11821         RSurf_ActiveWorldEntity();
11822
11823         surfaces = model->data_surfaces;
11824         update = model->brushq1.lightmapupdateflags;
11825
11826         // update light styles on this submodel
11827         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11828         {
11829                 model_brush_lightstyleinfo_t *style;
11830                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11831                 {
11832                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11833                         {
11834                                 int *list = style->surfacelist;
11835                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11836                                 for (j = 0;j < style->numsurfaces;j++)
11837                                         update[list[j]] = true;
11838                         }
11839                 }
11840         }
11841
11842         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11843
11844         if (debug)
11845         {
11846                 R_DrawDebugModel();
11847                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11848                 return;
11849         }
11850
11851         f = 0;
11852         t = NULL;
11853         rsurface.uselightmaptexture = false;
11854         rsurface.texture = NULL;
11855         rsurface.rtlight = NULL;
11856         numsurfacelist = 0;
11857         // add visible surfaces to draw list
11858         for (i = 0;i < model->nummodelsurfaces;i++)
11859         {
11860                 j = model->sortedmodelsurfaces[i];
11861                 if (r_refdef.viewcache.world_surfacevisible[j])
11862                         r_surfacelist[numsurfacelist++] = surfaces + j;
11863         }
11864         // update lightmaps if needed
11865         if (model->brushq1.firstrender)
11866         {
11867                 model->brushq1.firstrender = false;
11868                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11869                         if (update[j])
11870                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11871         }
11872         else if (update)
11873         {
11874                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11875                         if (r_refdef.viewcache.world_surfacevisible[j])
11876                                 if (update[j])
11877                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11878         }
11879         // don't do anything if there were no surfaces
11880         if (!numsurfacelist)
11881         {
11882                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11883                 return;
11884         }
11885         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11886         GL_AlphaTest(false);
11887
11888         // add to stats if desired
11889         if (r_speeds.integer && !skysurfaces && !depthonly)
11890         {
11891                 r_refdef.stats.world_surfaces += numsurfacelist;
11892                 for (j = 0;j < numsurfacelist;j++)
11893                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11894         }
11895
11896         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11897 }
11898
11899 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11900 {
11901         int i, j, endj, f, flagsmask;
11902         texture_t *t;
11903         dp_model_t *model = ent->model;
11904         msurface_t *surfaces;
11905         unsigned char *update;
11906         int numsurfacelist = 0;
11907         if (model == NULL)
11908                 return;
11909
11910         if (r_maxsurfacelist < model->num_surfaces)
11911         {
11912                 r_maxsurfacelist = model->num_surfaces;
11913                 if (r_surfacelist)
11914                         Mem_Free((msurface_t **)r_surfacelist);
11915                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11916         }
11917
11918         // if the model is static it doesn't matter what value we give for
11919         // wantnormals and wanttangents, so this logic uses only rules applicable
11920         // to a model, knowing that they are meaningless otherwise
11921         if (ent == r_refdef.scene.worldentity)
11922                 RSurf_ActiveWorldEntity();
11923         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11924                 RSurf_ActiveModelEntity(ent, false, false, false);
11925         else if (prepass)
11926                 RSurf_ActiveModelEntity(ent, true, true, true);
11927         else if (depthonly)
11928                 RSurf_ActiveModelEntity(ent, false, false, false);
11929         else
11930         {
11931                 switch (vid.renderpath)
11932                 {
11933                 case RENDERPATH_GL20:
11934                 case RENDERPATH_CGGL:
11935                         RSurf_ActiveModelEntity(ent, true, true, false);
11936                         break;
11937                 case RENDERPATH_GL13:
11938                 case RENDERPATH_GL11:
11939                         RSurf_ActiveModelEntity(ent, true, false, false);
11940                         break;
11941                 }
11942         }
11943
11944         surfaces = model->data_surfaces;
11945         update = model->brushq1.lightmapupdateflags;
11946
11947         // update light styles
11948         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11949         {
11950                 model_brush_lightstyleinfo_t *style;
11951                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11952                 {
11953                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11954                         {
11955                                 int *list = style->surfacelist;
11956                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11957                                 for (j = 0;j < style->numsurfaces;j++)
11958                                         update[list[j]] = true;
11959                         }
11960                 }
11961         }
11962
11963         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11964
11965         if (debug)
11966         {
11967                 R_DrawDebugModel();
11968                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11969                 return;
11970         }
11971
11972         f = 0;
11973         t = NULL;
11974         rsurface.uselightmaptexture = false;
11975         rsurface.texture = NULL;
11976         rsurface.rtlight = NULL;
11977         numsurfacelist = 0;
11978         // add visible surfaces to draw list
11979         for (i = 0;i < model->nummodelsurfaces;i++)
11980                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11981         // don't do anything if there were no surfaces
11982         if (!numsurfacelist)
11983         {
11984                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11985                 return;
11986         }
11987         // update lightmaps if needed
11988         if (update)
11989         {
11990                 int updated = 0;
11991                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11992                 {
11993                         if (update[j])
11994                         {
11995                                 updated++;
11996                                 R_BuildLightMap(ent, surfaces + j);
11997                         }
11998                 }
11999         }
12000         if (update)
12001                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12002                         if (update[j])
12003                                 R_BuildLightMap(ent, surfaces + j);
12004         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12005         GL_AlphaTest(false);
12006
12007         // add to stats if desired
12008         if (r_speeds.integer && !skysurfaces && !depthonly)
12009         {
12010                 r_refdef.stats.entities_surfaces += numsurfacelist;
12011                 for (j = 0;j < numsurfacelist;j++)
12012                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12013         }
12014
12015         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12016 }
12017
12018 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12019 {
12020         static texture_t texture;
12021         static msurface_t surface;
12022         const msurface_t *surfacelist = &surface;
12023
12024         // fake enough texture and surface state to render this geometry
12025
12026         texture.update_lastrenderframe = -1; // regenerate this texture
12027         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12028         texture.currentskinframe = skinframe;
12029         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12030         texture.specularscalemod = 1;
12031         texture.specularpowermod = 1;
12032
12033         surface.texture = &texture;
12034         surface.num_triangles = numtriangles;
12035         surface.num_firsttriangle = firsttriangle;
12036         surface.num_vertices = numvertices;
12037         surface.num_firstvertex = firstvertex;
12038
12039         // now render it
12040         rsurface.texture = R_GetCurrentTexture(surface.texture);
12041         rsurface.uselightmaptexture = false;
12042         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12043 }
12044
12045 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)
12046 {
12047         static msurface_t surface;
12048         const msurface_t *surfacelist = &surface;
12049
12050         // fake enough texture and surface state to render this geometry
12051
12052         surface.texture = texture;
12053         surface.num_triangles = numtriangles;
12054         surface.num_firsttriangle = firsttriangle;
12055         surface.num_vertices = numvertices;
12056         surface.num_firstvertex = firstvertex;
12057
12058         // now render it
12059         rsurface.texture = R_GetCurrentTexture(surface.texture);
12060         rsurface.uselightmaptexture = false;
12061         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12062 }