]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
more reductions in memory usage
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
73 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
74 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
96 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
102
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
111
112 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
113 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
114
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
118
119 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
125 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
126 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
127 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
128
129 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
134
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
139
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
147
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
152
153 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
154
155 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
156
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
158
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
166
167 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
168
169 extern cvar_t v_glslgamma;
170
171 extern qboolean v_flipped_state;
172
173 static struct r_bloomstate_s
174 {
175         qboolean enabled;
176         qboolean hdr;
177
178         int bloomwidth, bloomheight;
179
180         int screentexturewidth, screentextureheight;
181         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
182
183         int bloomtexturewidth, bloomtextureheight;
184         rtexture_t *texture_bloom;
185
186         // arrays for rendering the screen passes
187         float screentexcoord2f[8];
188         float bloomtexcoord2f[8];
189         float offsettexcoord2f[8];
190
191         r_viewport_t viewport;
192 }
193 r_bloomstate;
194
195 r_waterstate_t r_waterstate;
196
197 /// shadow volume bsp struct with automatically growing nodes buffer
198 svbsp_t r_svbsp;
199
200 rtexture_t *r_texture_blanknormalmap;
201 rtexture_t *r_texture_white;
202 rtexture_t *r_texture_grey128;
203 rtexture_t *r_texture_black;
204 rtexture_t *r_texture_notexture;
205 rtexture_t *r_texture_whitecube;
206 rtexture_t *r_texture_normalizationcube;
207 rtexture_t *r_texture_fogattenuation;
208 rtexture_t *r_texture_gammaramps;
209 unsigned int r_texture_gammaramps_serial;
210 //rtexture_t *r_texture_fogintensity;
211
212 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
213 unsigned int r_numqueries;
214 unsigned int r_maxqueries;
215
216 typedef struct r_qwskincache_s
217 {
218         char name[MAX_QPATH];
219         skinframe_t *skinframe;
220 }
221 r_qwskincache_t;
222
223 static r_qwskincache_t *r_qwskincache;
224 static int r_qwskincache_size;
225
226 /// vertex coordinates for a quad that covers the screen exactly
227 const float r_screenvertex3f[12] =
228 {
229         0, 0, 0,
230         1, 0, 0,
231         1, 1, 0,
232         0, 1, 0
233 };
234
235 extern void R_DrawModelShadows(void);
236
237 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
238 {
239         int i;
240         for (i = 0;i < verts;i++)
241         {
242                 out[0] = in[0] * r;
243                 out[1] = in[1] * g;
244                 out[2] = in[2] * b;
245                 out[3] = in[3];
246                 in += 4;
247                 out += 4;
248         }
249 }
250
251 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
252 {
253         int i;
254         for (i = 0;i < verts;i++)
255         {
256                 out[0] = r;
257                 out[1] = g;
258                 out[2] = b;
259                 out[3] = a;
260                 out += 4;
261         }
262 }
263
264 // FIXME: move this to client?
265 void FOG_clear(void)
266 {
267         if (gamemode == GAME_NEHAHRA)
268         {
269                 Cvar_Set("gl_fogenable", "0");
270                 Cvar_Set("gl_fogdensity", "0.2");
271                 Cvar_Set("gl_fogred", "0.3");
272                 Cvar_Set("gl_foggreen", "0.3");
273                 Cvar_Set("gl_fogblue", "0.3");
274         }
275         r_refdef.fog_density = 0;
276         r_refdef.fog_red = 0;
277         r_refdef.fog_green = 0;
278         r_refdef.fog_blue = 0;
279         r_refdef.fog_alpha = 1;
280         r_refdef.fog_start = 0;
281         r_refdef.fog_end = 16384;
282         r_refdef.fog_height = 1<<30;
283         r_refdef.fog_fadedepth = 128;
284 }
285
286 static void R_BuildBlankTextures(void)
287 {
288         unsigned char data[4];
289         data[2] = 128; // normal X
290         data[1] = 128; // normal Y
291         data[0] = 255; // normal Z
292         data[3] = 128; // height
293         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
294         data[0] = 255;
295         data[1] = 255;
296         data[2] = 255;
297         data[3] = 255;
298         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
299         data[0] = 128;
300         data[1] = 128;
301         data[2] = 128;
302         data[3] = 255;
303         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
304         data[0] = 0;
305         data[1] = 0;
306         data[2] = 0;
307         data[3] = 255;
308         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
309 }
310
311 static void R_BuildNoTexture(void)
312 {
313         int x, y;
314         unsigned char pix[16][16][4];
315         // this makes a light grey/dark grey checkerboard texture
316         for (y = 0;y < 16;y++)
317         {
318                 for (x = 0;x < 16;x++)
319                 {
320                         if ((y < 8) ^ (x < 8))
321                         {
322                                 pix[y][x][0] = 128;
323                                 pix[y][x][1] = 128;
324                                 pix[y][x][2] = 128;
325                                 pix[y][x][3] = 255;
326                         }
327                         else
328                         {
329                                 pix[y][x][0] = 64;
330                                 pix[y][x][1] = 64;
331                                 pix[y][x][2] = 64;
332                                 pix[y][x][3] = 255;
333                         }
334                 }
335         }
336         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
337 }
338
339 static void R_BuildWhiteCube(void)
340 {
341         unsigned char data[6*1*1*4];
342         memset(data, 255, sizeof(data));
343         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
344 }
345
346 static void R_BuildNormalizationCube(void)
347 {
348         int x, y, side;
349         vec3_t v;
350         vec_t s, t, intensity;
351 #define NORMSIZE 64
352         unsigned char *data;
353         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
354         for (side = 0;side < 6;side++)
355         {
356                 for (y = 0;y < NORMSIZE;y++)
357                 {
358                         for (x = 0;x < NORMSIZE;x++)
359                         {
360                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
361                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
362                                 switch(side)
363                                 {
364                                 default:
365                                 case 0:
366                                         v[0] = 1;
367                                         v[1] = -t;
368                                         v[2] = -s;
369                                         break;
370                                 case 1:
371                                         v[0] = -1;
372                                         v[1] = -t;
373                                         v[2] = s;
374                                         break;
375                                 case 2:
376                                         v[0] = s;
377                                         v[1] = 1;
378                                         v[2] = t;
379                                         break;
380                                 case 3:
381                                         v[0] = s;
382                                         v[1] = -1;
383                                         v[2] = -t;
384                                         break;
385                                 case 4:
386                                         v[0] = s;
387                                         v[1] = -t;
388                                         v[2] = 1;
389                                         break;
390                                 case 5:
391                                         v[0] = -s;
392                                         v[1] = -t;
393                                         v[2] = -1;
394                                         break;
395                                 }
396                                 intensity = 127.0f / sqrt(DotProduct(v, v));
397                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
398                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
399                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
400                                 data[((side*64+y)*64+x)*4+3] = 255;
401                         }
402                 }
403         }
404         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
405         Mem_Free(data);
406 }
407
408 static void R_BuildFogTexture(void)
409 {
410         int x, b;
411 #define FOGWIDTH 256
412         unsigned char data1[FOGWIDTH][4];
413         //unsigned char data2[FOGWIDTH][4];
414         double d, r, alpha;
415
416         r_refdef.fogmasktable_start = r_refdef.fog_start;
417         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
418         r_refdef.fogmasktable_range = r_refdef.fogrange;
419         r_refdef.fogmasktable_density = r_refdef.fog_density;
420
421         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
422         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
423         {
424                 d = (x * r - r_refdef.fogmasktable_start);
425                 if(developer_extra.integer)
426                         Con_DPrintf("%f ", d);
427                 d = max(0, d);
428                 if (r_fog_exp2.integer)
429                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
430                 else
431                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
432                 if(developer_extra.integer)
433                         Con_DPrintf(" : %f ", alpha);
434                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
435                 if(developer_extra.integer)
436                         Con_DPrintf(" = %f\n", alpha);
437                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
438         }
439
440         for (x = 0;x < FOGWIDTH;x++)
441         {
442                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
443                 data1[x][0] = b;
444                 data1[x][1] = b;
445                 data1[x][2] = b;
446                 data1[x][3] = 255;
447                 //data2[x][0] = 255 - b;
448                 //data2[x][1] = 255 - b;
449                 //data2[x][2] = 255 - b;
450                 //data2[x][3] = 255;
451         }
452         if (r_texture_fogattenuation)
453         {
454                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
455                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
456         }
457         else
458         {
459                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
460                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
461         }
462 }
463
464 //=======================================================================================================================================================
465
466 static const char *builtinshaderstring =
467 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
468 "// written by Forest 'LordHavoc' Hale\n"
469 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
470 "\n"
471 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
472 "# define USEFOG\n"
473 "#endif\n"
474 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
475 "#define USELIGHTMAP\n"
476 "#endif\n"
477 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
478 "#define USEEYEVECTOR\n"
479 "#endif\n"
480 "\n"
481 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
482 "# extension GL_ARB_texture_rectangle : enable\n"
483 "#endif\n"
484 "\n"
485 "#ifdef USESHADOWMAP2D\n"
486 "# ifdef GL_EXT_gpu_shader4\n"
487 "#   extension GL_EXT_gpu_shader4 : enable\n"
488 "# endif\n"
489 "# ifdef GL_ARB_texture_gather\n"
490 "#   extension GL_ARB_texture_gather : enable\n"
491 "# else\n"
492 "#   ifdef GL_AMD_texture_texture4\n"
493 "#     extension GL_AMD_texture_texture4 : enable\n"
494 "#   endif\n"
495 "# endif\n"
496 "#endif\n"
497 "\n"
498 "#ifdef USESHADOWMAPCUBE\n"
499 "# extension GL_EXT_gpu_shader4 : enable\n"
500 "#endif\n"
501 "\n"
502 "//#ifdef USESHADOWSAMPLER\n"
503 "//# extension GL_ARB_shadow : enable\n"
504 "//#endif\n"
505 "\n"
506 "//#ifdef __GLSL_CG_DATA_TYPES\n"
507 "//# define myhalf half\n"
508 "//# define myhalf2 half2\n"
509 "//# define myhalf3 half3\n"
510 "//# define myhalf4 half4\n"
511 "//#else\n"
512 "# define myhalf float\n"
513 "# define myhalf2 vec2\n"
514 "# define myhalf3 vec3\n"
515 "# define myhalf4 vec4\n"
516 "//#endif\n"
517 "\n"
518 "#ifdef VERTEX_SHADER\n"
519 "uniform mat4 ModelViewProjectionMatrix;\n"
520 "#endif\n"
521 "\n"
522 "#ifdef MODE_DEPTH_OR_SHADOW\n"
523 "#ifdef VERTEX_SHADER\n"
524 "void main(void)\n"
525 "{\n"
526 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
527 "}\n"
528 "#endif\n"
529 "#else // !MODE_DEPTH_ORSHADOW\n"
530 "\n"
531 "\n"
532 "\n"
533 "\n"
534 "#ifdef MODE_SHOWDEPTH\n"
535 "#ifdef VERTEX_SHADER\n"
536 "void main(void)\n"
537 "{\n"
538 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
539 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
540 "}\n"
541 "#endif\n"
542 "\n"
543 "#ifdef FRAGMENT_SHADER\n"
544 "void main(void)\n"
545 "{\n"
546 "       gl_FragColor = gl_Color;\n"
547 "}\n"
548 "#endif\n"
549 "#else // !MODE_SHOWDEPTH\n"
550 "\n"
551 "\n"
552 "\n"
553 "\n"
554 "#ifdef MODE_POSTPROCESS\n"
555 "varying vec2 TexCoord1;\n"
556 "varying vec2 TexCoord2;\n"
557 "\n"
558 "#ifdef VERTEX_SHADER\n"
559 "void main(void)\n"
560 "{\n"
561 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
562 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
563 "#ifdef USEBLOOM\n"
564 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
565 "#endif\n"
566 "}\n"
567 "#endif\n"
568 "\n"
569 "#ifdef FRAGMENT_SHADER\n"
570 "uniform sampler2D Texture_First;\n"
571 "#ifdef USEBLOOM\n"
572 "uniform sampler2D Texture_Second;\n"
573 "#endif\n"
574 "#ifdef USEGAMMARAMPS\n"
575 "uniform sampler2D Texture_GammaRamps;\n"
576 "#endif\n"
577 "#ifdef USESATURATION\n"
578 "uniform float Saturation;\n"
579 "#endif\n"
580 "#ifdef USEVIEWTINT\n"
581 "uniform vec4 ViewTintColor;\n"
582 "#endif\n"
583 "//uncomment these if you want to use them:\n"
584 "uniform vec4 UserVec1;\n"
585 "// uniform vec4 UserVec2;\n"
586 "// uniform vec4 UserVec3;\n"
587 "// uniform vec4 UserVec4;\n"
588 "// uniform float ClientTime;\n"
589 "uniform vec2 PixelSize;\n"
590 "void main(void)\n"
591 "{\n"
592 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
593 "#ifdef USEBLOOM\n"
594 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
595 "#endif\n"
596 "#ifdef USEVIEWTINT\n"
597 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
598 "#endif\n"
599 "\n"
600 "#ifdef USEPOSTPROCESSING\n"
601 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
602 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
603 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
604 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
605 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
606 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
607 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
608 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
609 "#endif\n"
610 "\n"
611 "#ifdef USESATURATION\n"
612 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
613 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
614 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
615 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
616 "#endif\n"
617 "\n"
618 "#ifdef USEGAMMARAMPS\n"
619 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
620 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
621 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
622 "#endif\n"
623 "}\n"
624 "#endif\n"
625 "#else // !MODE_POSTPROCESS\n"
626 "\n"
627 "\n"
628 "\n"
629 "\n"
630 "#ifdef MODE_GENERIC\n"
631 "#ifdef USEDIFFUSE\n"
632 "varying vec2 TexCoord1;\n"
633 "#endif\n"
634 "#ifdef USESPECULAR\n"
635 "varying vec2 TexCoord2;\n"
636 "#endif\n"
637 "#ifdef VERTEX_SHADER\n"
638 "void main(void)\n"
639 "{\n"
640 "       gl_FrontColor = gl_Color;\n"
641 "#ifdef USEDIFFUSE\n"
642 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
643 "#endif\n"
644 "#ifdef USESPECULAR\n"
645 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
646 "#endif\n"
647 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
648 "}\n"
649 "#endif\n"
650 "\n"
651 "#ifdef FRAGMENT_SHADER\n"
652 "#ifdef USEDIFFUSE\n"
653 "uniform sampler2D Texture_First;\n"
654 "#endif\n"
655 "#ifdef USESPECULAR\n"
656 "uniform sampler2D Texture_Second;\n"
657 "#endif\n"
658 "\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FragColor = gl_Color;\n"
662 "#ifdef USEDIFFUSE\n"
663 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
664 "#endif\n"
665 "\n"
666 "#ifdef USESPECULAR\n"
667 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
668 "# ifdef USECOLORMAPPING\n"
669 "       gl_FragColor *= tex2;\n"
670 "# endif\n"
671 "# ifdef USEGLOW\n"
672 "       gl_FragColor += tex2;\n"
673 "# endif\n"
674 "# ifdef USEVERTEXTEXTUREBLEND\n"
675 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
676 "# endif\n"
677 "#endif\n"
678 "}\n"
679 "#endif\n"
680 "#else // !MODE_GENERIC\n"
681 "\n"
682 "\n"
683 "\n"
684 "\n"
685 "#ifdef MODE_BLOOMBLUR\n"
686 "varying TexCoord;\n"
687 "#ifdef VERTEX_SHADER\n"
688 "void main(void)\n"
689 "{\n"
690 "       gl_FrontColor = gl_Color;\n"
691 "       TexCoord = gl_MultiTexCoord0.xy;\n"
692 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
693 "}\n"
694 "#endif\n"
695 "\n"
696 "#ifdef FRAGMENT_SHADER\n"
697 "uniform sampler2D Texture_First;\n"
698 "uniform vec4 BloomBlur_Parameters;\n"
699 "\n"
700 "void main(void)\n"
701 "{\n"
702 "       int i;\n"
703 "       vec2 tc = TexCoord;\n"
704 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
705 "       tc += BloomBlur_Parameters.xy;\n"
706 "       for (i = 1;i < SAMPLES;i++)\n"
707 "       {\n"
708 "               color += texture2D(Texture_First, tc).rgb;\n"
709 "               tc += BloomBlur_Parameters.xy;\n"
710 "       }\n"
711 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
712 "}\n"
713 "#endif\n"
714 "#else // !MODE_BLOOMBLUR\n"
715 "#ifdef MODE_REFRACTION\n"
716 "varying vec2 TexCoord;\n"
717 "varying vec4 ModelViewProjectionPosition;\n"
718 "uniform mat4 TexMatrix;\n"
719 "#ifdef VERTEX_SHADER\n"
720 "\n"
721 "void main(void)\n"
722 "{\n"
723 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
724 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
725 "       ModelViewProjectionPosition = gl_Position;\n"
726 "}\n"
727 "#endif\n"
728 "\n"
729 "#ifdef FRAGMENT_SHADER\n"
730 "uniform sampler2D Texture_Normal;\n"
731 "uniform sampler2D Texture_Refraction;\n"
732 "uniform sampler2D Texture_Reflection;\n"
733 "\n"
734 "uniform vec4 DistortScaleRefractReflect;\n"
735 "uniform vec4 ScreenScaleRefractReflect;\n"
736 "uniform vec4 ScreenCenterRefractReflect;\n"
737 "uniform vec4 RefractColor;\n"
738 "uniform vec4 ReflectColor;\n"
739 "uniform float ReflectFactor;\n"
740 "uniform float ReflectOffset;\n"
741 "\n"
742 "void main(void)\n"
743 "{\n"
744 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
745 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
746 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
747 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
748 "       // FIXME temporary hack to detect the case that the reflection\n"
749 "       // gets blackened at edges due to leaving the area that contains actual\n"
750 "       // content.\n"
751 "       // Remove this 'ack once we have a better way to stop this thing from\n"
752 "       // 'appening.\n"
753 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
754 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
755 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
756 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
757 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
758 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
759 "}\n"
760 "#endif\n"
761 "#else // !MODE_REFRACTION\n"
762 "\n"
763 "\n"
764 "\n"
765 "\n"
766 "#ifdef MODE_WATER\n"
767 "varying vec2 TexCoord;\n"
768 "varying vec3 EyeVector;\n"
769 "varying vec4 ModelViewProjectionPosition;\n"
770 "#ifdef VERTEX_SHADER\n"
771 "uniform vec3 EyePosition;\n"
772 "uniform mat4 TexMatrix;\n"
773 "\n"
774 "void main(void)\n"
775 "{\n"
776 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
777 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
778 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
779 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
780 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
781 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
782 "       ModelViewProjectionPosition = gl_Position;\n"
783 "}\n"
784 "#endif\n"
785 "\n"
786 "#ifdef FRAGMENT_SHADER\n"
787 "uniform sampler2D Texture_Normal;\n"
788 "uniform sampler2D Texture_Refraction;\n"
789 "uniform sampler2D Texture_Reflection;\n"
790 "\n"
791 "uniform vec4 DistortScaleRefractReflect;\n"
792 "uniform vec4 ScreenScaleRefractReflect;\n"
793 "uniform vec4 ScreenCenterRefractReflect;\n"
794 "uniform vec4 RefractColor;\n"
795 "uniform vec4 ReflectColor;\n"
796 "uniform float ReflectFactor;\n"
797 "uniform float ReflectOffset;\n"
798 "\n"
799 "void main(void)\n"
800 "{\n"
801 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
802 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
803 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
804 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
805 "       // FIXME temporary hack to detect the case that the reflection\n"
806 "       // gets blackened at edges due to leaving the area that contains actual\n"
807 "       // content.\n"
808 "       // Remove this 'ack once we have a better way to stop this thing from\n"
809 "       // 'appening.\n"
810 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
811 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
812 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
813 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
814 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
815 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
816 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
817 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
818 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
819 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
820 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
821 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
822 "}\n"
823 "#endif\n"
824 "#else // !MODE_WATER\n"
825 "\n"
826 "\n"
827 "\n"
828 "\n"
829 "// common definitions between vertex shader and fragment shader:\n"
830 "\n"
831 "varying vec2 TexCoord;\n"
832 "#ifdef USEVERTEXTEXTUREBLEND\n"
833 "varying vec2 TexCoord2;\n"
834 "#endif\n"
835 "#ifdef USELIGHTMAP\n"
836 "varying vec2 TexCoordLightmap;\n"
837 "#endif\n"
838 "\n"
839 "#ifdef MODE_LIGHTSOURCE\n"
840 "varying vec3 CubeVector;\n"
841 "#endif\n"
842 "\n"
843 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
844 "varying vec3 LightVector;\n"
845 "#endif\n"
846 "\n"
847 "#ifdef USEEYEVECTOR\n"
848 "varying vec3 EyeVector;\n"
849 "#endif\n"
850 "#ifdef USEFOG\n"
851 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
852 "#endif\n"
853 "\n"
854 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
855 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
856 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
857 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
858 "#endif\n"
859 "\n"
860 "#ifdef USEREFLECTION\n"
861 "varying vec4 ModelViewProjectionPosition;\n"
862 "#endif\n"
863 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
864 "uniform vec3 LightPosition;\n"
865 "varying vec4 ModelViewPosition;\n"
866 "#endif\n"
867 "\n"
868 "#ifdef MODE_LIGHTSOURCE\n"
869 "uniform vec3 LightPosition;\n"
870 "#endif\n"
871 "uniform vec3 EyePosition;\n"
872 "#ifdef MODE_LIGHTDIRECTION\n"
873 "uniform vec3 LightDir;\n"
874 "#endif\n"
875 "uniform vec4 FogPlane;\n"
876 "\n"
877 "\n"
878 "\n"
879 "\n"
880 "\n"
881 "// 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"
882 "\n"
883 "// fragment shader specific:\n"
884 "#ifdef FRAGMENT_SHADER\n"
885 "\n"
886 "uniform sampler2D Texture_Normal;\n"
887 "uniform sampler2D Texture_Color;\n"
888 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
889 "uniform sampler2D Texture_Gloss;\n"
890 "//#endif\n"
891 "#ifdef USEGLOW\n"
892 "uniform sampler2D Texture_Glow;\n"
893 "#endif\n"
894 "#ifdef USEVERTEXTEXTUREBLEND\n"
895 "uniform sampler2D Texture_SecondaryNormal;\n"
896 "uniform sampler2D Texture_SecondaryColor;\n"
897 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
898 "uniform sampler2D Texture_SecondaryGloss;\n"
899 "//#endif\n"
900 "#ifdef USEGLOW\n"
901 "uniform sampler2D Texture_SecondaryGlow;\n"
902 "#endif\n"
903 "#endif\n"
904 "#ifdef USECOLORMAPPING\n"
905 "uniform sampler2D Texture_Pants;\n"
906 "uniform sampler2D Texture_Shirt;\n"
907 "#endif\n"
908 "#ifdef USEFOG\n"
909 "uniform sampler2D Texture_FogMask;\n"
910 "#endif\n"
911 "#ifdef USELIGHTMAP\n"
912 "uniform sampler2D Texture_Lightmap;\n"
913 "#endif\n"
914 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
915 "uniform sampler2D Texture_Deluxemap;\n"
916 "#endif\n"
917 "#ifdef USEREFLECTION\n"
918 "uniform sampler2D Texture_Reflection;\n"
919 "#endif\n"
920 "\n"
921 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
922 "uniform sampler2D Texture_ScreenDepth;\n"
923 "uniform sampler2D Texture_ScreenNormalMap;\n"
924 "#endif\n"
925 "#ifdef USEDEFERREDLIGHTMAP\n"
926 "uniform sampler2D Texture_ScreenDiffuse;\n"
927 "uniform sampler2D Texture_ScreenSpecular;\n"
928 "#endif\n"
929 "\n"
930 "uniform myhalf3 Color_Pants;\n"
931 "uniform myhalf3 Color_Shirt;\n"
932 "uniform myhalf3 FogColor;\n"
933 "\n"
934 "#ifdef USEFOG\n"
935 "uniform float FogRangeRecip;\n"
936 "uniform float FogPlaneViewDist;\n"
937 "uniform float FogHeightFade;\n"
938 "float FogVertex(void)\n"
939 "{\n"
940 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
941 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
942 "       float fogfrac;\n"
943 "#ifdef USEFOGOUTSIDE\n"
944 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
945 "#else\n"
946 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
947 "#endif\n"
948 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
949 "}\n"
950 "#endif\n"
951 "\n"
952 "#ifdef USEOFFSETMAPPING\n"
953 "uniform float OffsetMapping_Scale;\n"
954 "vec2 OffsetMapping(vec2 TexCoord)\n"
955 "{\n"
956 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
957 "       // 14 sample relief mapping: linear search and then binary search\n"
958 "       // this basically steps forward a small amount repeatedly until it finds\n"
959 "       // itself inside solid, then jitters forward and back using decreasing\n"
960 "       // amounts to find the impact\n"
961 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
962 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
963 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
964 "       vec3 RT = vec3(TexCoord, 1);\n"
965 "       OffsetVector *= 0.1;\n"
966 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
967 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
968 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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)          - 0.5);\n"
976 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
977 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
978 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
979 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
980 "       return RT.xy;\n"
981 "#else\n"
982 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
983 "       // this basically moves forward the full distance, and then backs up based\n"
984 "       // on height of samples\n"
985 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
986 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
987 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
988 "       TexCoord += OffsetVector;\n"
989 "       OffsetVector *= 0.333;\n"
990 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
991 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
992 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
993 "       return TexCoord;\n"
994 "#endif\n"
995 "}\n"
996 "#endif // USEOFFSETMAPPING\n"
997 "\n"
998 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
999 "uniform sampler2D Texture_Attenuation;\n"
1000 "uniform samplerCube Texture_Cube;\n"
1001 "\n"
1002 "#ifdef USESHADOWMAPRECT\n"
1003 "# ifdef USESHADOWSAMPLER\n"
1004 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1005 "# else\n"
1006 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1007 "# endif\n"
1008 "#endif\n"
1009 "\n"
1010 "#ifdef USESHADOWMAP2D\n"
1011 "# ifdef USESHADOWSAMPLER\n"
1012 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1013 "# else\n"
1014 "uniform sampler2D Texture_ShadowMap2D;\n"
1015 "# endif\n"
1016 "#endif\n"
1017 "\n"
1018 "#ifdef USESHADOWMAPVSDCT\n"
1019 "uniform samplerCube Texture_CubeProjection;\n"
1020 "#endif\n"
1021 "\n"
1022 "#ifdef USESHADOWMAPCUBE\n"
1023 "# ifdef USESHADOWSAMPLER\n"
1024 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1025 "# else\n"
1026 "uniform samplerCube Texture_ShadowMapCube;\n"
1027 "# endif\n"
1028 "#endif\n"
1029 "\n"
1030 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1031 "uniform vec2 ShadowMap_TextureScale;\n"
1032 "uniform vec4 ShadowMap_Parameters;\n"
1033 "#endif\n"
1034 "\n"
1035 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1036 "# ifndef USESHADOWMAPVSDCT\n"
1037 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1038 "{\n"
1039 "       vec3 adir = abs(dir);\n"
1040 "       vec2 tc;\n"
1041 "       vec2 offset;\n"
1042 "       float ma;\n"
1043 "       if (adir.x > adir.y)\n"
1044 "       {\n"
1045 "               if (adir.x > adir.z) // X\n"
1046 "               {\n"
1047 "                       ma = adir.x;\n"
1048 "                       tc = dir.zy;\n"
1049 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1050 "               }\n"
1051 "               else // Z\n"
1052 "               {\n"
1053 "                       ma = adir.z;\n"
1054 "                       tc = dir.xy;\n"
1055 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1056 "               }\n"
1057 "       }\n"
1058 "       else\n"
1059 "       {\n"
1060 "               if (adir.y > adir.z) // Y\n"
1061 "               {\n"
1062 "                       ma = adir.y;\n"
1063 "                       tc = dir.xz;\n"
1064 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1065 "               }\n"
1066 "               else // Z\n"
1067 "               {\n"
1068 "                       ma = adir.z;\n"
1069 "                       tc = dir.xy;\n"
1070 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1071 "               }\n"
1072 "       }\n"
1073 "\n"
1074 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1075 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1076 "       stc.z += ShadowMap_Parameters.z;\n"
1077 "       return stc;\n"
1078 "}\n"
1079 "# else\n"
1080 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1081 "{\n"
1082 "       vec3 adir = abs(dir);\n"
1083 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1084 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1085 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1086 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1087 "       stc.z += ShadowMap_Parameters.z;\n"
1088 "       return stc;\n"
1089 "}\n"
1090 "# endif\n"
1091 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1092 "\n"
1093 "#ifdef USESHADOWMAPCUBE\n"
1094 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1095 "{\n"
1096 "       vec3 adir = abs(dir);\n"
1097 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1098 "}\n"
1099 "#endif\n"
1100 "\n"
1101 "# ifdef USESHADOWMAPRECT\n"
1102 "float ShadowMapCompare(vec3 dir)\n"
1103 "{\n"
1104 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1105 "       float f;\n"
1106 "#  ifdef USESHADOWSAMPLER\n"
1107 "\n"
1108 "#    ifdef USESHADOWMAPPCF\n"
1109 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1110 "       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"
1111 "#    else\n"
1112 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1113 "#    endif\n"
1114 "\n"
1115 "#  else\n"
1116 "\n"
1117 "#    ifdef USESHADOWMAPPCF\n"
1118 "#      if USESHADOWMAPPCF > 1\n"
1119 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1120 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1121 "       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"
1122 "       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"
1123 "       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"
1124 "       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"
1125 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1126 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1127 "#      else\n"
1128 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1129 "       vec2 offset = fract(shadowmaptc.xy);\n"
1130 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1131 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1132 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1133 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1134 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1135 "#      endif\n"
1136 "#    else\n"
1137 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1138 "#    endif\n"
1139 "\n"
1140 "#  endif\n"
1141 "       return f;\n"
1142 "}\n"
1143 "# endif\n"
1144 "\n"
1145 "# ifdef USESHADOWMAP2D\n"
1146 "float ShadowMapCompare(vec3 dir)\n"
1147 "{\n"
1148 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1149 "       float f;\n"
1150 "\n"
1151 "#  ifdef USESHADOWSAMPLER\n"
1152 "#    ifdef USESHADOWMAPPCF\n"
1153 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1154 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1155 "       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"
1156 "#    else\n"
1157 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1158 "#    endif\n"
1159 "#  else\n"
1160 "#    ifdef USESHADOWMAPPCF\n"
1161 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1162 "#      ifdef GL_ARB_texture_gather\n"
1163 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1164 "#      else\n"
1165 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1166 "#      endif\n"
1167 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1168 "       center *= ShadowMap_TextureScale;\n"
1169 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1170 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1171 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1172 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1173 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1174 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1175 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1176 "#     else\n"
1177 "#      ifdef GL_EXT_gpu_shader4\n"
1178 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1179 "#      else\n"
1180 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1181 "#      endif\n"
1182 "#      if USESHADOWMAPPCF > 1\n"
1183 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1184 "       center *= ShadowMap_TextureScale;\n"
1185 "       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"
1186 "       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"
1187 "       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"
1188 "       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"
1189 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1190 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1191 "#      else\n"
1192 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1193 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1194 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1195 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1196 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1197 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1198 "#      endif\n"
1199 "#     endif\n"
1200 "#    else\n"
1201 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1202 "#    endif\n"
1203 "#  endif\n"
1204 "       return f;\n"
1205 "}\n"
1206 "# endif\n"
1207 "\n"
1208 "# ifdef USESHADOWMAPCUBE\n"
1209 "float ShadowMapCompare(vec3 dir)\n"
1210 "{\n"
1211 "       // apply depth texture cubemap as light filter\n"
1212 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1213 "       float f;\n"
1214 "#  ifdef USESHADOWSAMPLER\n"
1215 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1216 "#  else\n"
1217 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1218 "#  endif\n"
1219 "       return f;\n"
1220 "}\n"
1221 "# endif\n"
1222 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1223 "#endif // FRAGMENT_SHADER\n"
1224 "\n"
1225 "\n"
1226 "\n"
1227 "\n"
1228 "#ifdef MODE_DEFERREDGEOMETRY\n"
1229 "#ifdef VERTEX_SHADER\n"
1230 "uniform mat4 TexMatrix;\n"
1231 "#ifdef USEVERTEXTEXTUREBLEND\n"
1232 "uniform mat4 BackgroundTexMatrix;\n"
1233 "#endif\n"
1234 "uniform mat4 ModelViewMatrix;\n"
1235 "void main(void)\n"
1236 "{\n"
1237 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1238 "#ifdef USEVERTEXTEXTUREBLEND\n"
1239 "       gl_FrontColor = gl_Color;\n"
1240 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1241 "#endif\n"
1242 "\n"
1243 "       // transform unnormalized eye direction into tangent space\n"
1244 "#ifdef USEOFFSETMAPPING\n"
1245 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1246 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1247 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1248 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1249 "#endif\n"
1250 "\n"
1251 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1252 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1253 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1254 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1255 "}\n"
1256 "#endif // VERTEX_SHADER\n"
1257 "\n"
1258 "#ifdef FRAGMENT_SHADER\n"
1259 "void main(void)\n"
1260 "{\n"
1261 "#ifdef USEOFFSETMAPPING\n"
1262 "       // apply offsetmapping\n"
1263 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1264 "#define TexCoord TexCoordOffset\n"
1265 "#endif\n"
1266 "\n"
1267 "#ifdef USEALPHAKILL\n"
1268 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1269 "               discard;\n"
1270 "#endif\n"
1271 "\n"
1272 "#ifdef USEVERTEXTEXTUREBLEND\n"
1273 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1274 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1275 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1276 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1277 "#endif\n"
1278 "\n"
1279 "#ifdef USEVERTEXTEXTUREBLEND\n"
1280 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1281 "#else\n"
1282 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1283 "#endif\n"
1284 "\n"
1285 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1286 "}\n"
1287 "#endif // FRAGMENT_SHADER\n"
1288 "#else // !MODE_DEFERREDGEOMETRY\n"
1289 "\n"
1290 "\n"
1291 "\n"
1292 "\n"
1293 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1294 "#ifdef VERTEX_SHADER\n"
1295 "uniform mat4 ModelViewMatrix;\n"
1296 "void main(void)\n"
1297 "{\n"
1298 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1299 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1300 "}\n"
1301 "#endif // VERTEX_SHADER\n"
1302 "\n"
1303 "#ifdef FRAGMENT_SHADER\n"
1304 "uniform mat4 ViewToLight;\n"
1305 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1306 "uniform vec2 ScreenToDepth;\n"
1307 "uniform myhalf3 DeferredColor_Ambient;\n"
1308 "uniform myhalf3 DeferredColor_Diffuse;\n"
1309 "#ifdef USESPECULAR\n"
1310 "uniform myhalf3 DeferredColor_Specular;\n"
1311 "uniform myhalf SpecularPower;\n"
1312 "#endif\n"
1313 "uniform myhalf2 PixelToScreenTexCoord;\n"
1314 "void main(void)\n"
1315 "{\n"
1316 "       // calculate viewspace pixel position\n"
1317 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1318 "       vec3 position;\n"
1319 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1320 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1321 "       // decode viewspace pixel normal\n"
1322 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1323 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1324 "       // surfacenormal = pixel normal in viewspace\n"
1325 "       // LightVector = pixel to light in viewspace\n"
1326 "       // CubeVector = position in lightspace\n"
1327 "       // eyevector = pixel to view in viewspace\n"
1328 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1329 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1330 "#ifdef USEDIFFUSE\n"
1331 "       // calculate diffuse shading\n"
1332 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1333 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1334 "#endif\n"
1335 "#ifdef USESPECULAR\n"
1336 "       // calculate directional shading\n"
1337 "       vec3 eyevector = position * -1.0;\n"
1338 "#  ifdef USEEXACTSPECULARMATH\n"
1339 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1340 "#  else\n"
1341 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1342 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1343 "#  endif\n"
1344 "#endif\n"
1345 "\n"
1346 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1347 "       fade *= ShadowMapCompare(CubeVector);\n"
1348 "#endif\n"
1349 "\n"
1350 "#ifdef USEDIFFUSE\n"
1351 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1352 "#else\n"
1353 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1354 "#endif\n"
1355 "#ifdef USESPECULAR\n"
1356 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1357 "#else\n"
1358 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1359 "#endif\n"
1360 "\n"
1361 "# ifdef USECUBEFILTER\n"
1362 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1363 "       gl_FragData[0].rgb *= cubecolor;\n"
1364 "       gl_FragData[1].rgb *= cubecolor;\n"
1365 "# endif\n"
1366 "}\n"
1367 "#endif // FRAGMENT_SHADER\n"
1368 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1369 "\n"
1370 "\n"
1371 "\n"
1372 "\n"
1373 "#ifdef VERTEX_SHADER\n"
1374 "uniform mat4 TexMatrix;\n"
1375 "#ifdef USEVERTEXTEXTUREBLEND\n"
1376 "uniform mat4 BackgroundTexMatrix;\n"
1377 "#endif\n"
1378 "#ifdef MODE_LIGHTSOURCE\n"
1379 "uniform mat4 ModelToLight;\n"
1380 "#endif\n"
1381 "void main(void)\n"
1382 "{\n"
1383 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1384 "       gl_FrontColor = gl_Color;\n"
1385 "#endif\n"
1386 "       // copy the surface texcoord\n"
1387 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1388 "#ifdef USEVERTEXTEXTUREBLEND\n"
1389 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1390 "#endif\n"
1391 "#ifdef USELIGHTMAP\n"
1392 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1393 "#endif\n"
1394 "\n"
1395 "#ifdef MODE_LIGHTSOURCE\n"
1396 "       // transform vertex position into light attenuation/cubemap space\n"
1397 "       // (-1 to +1 across the light box)\n"
1398 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1399 "\n"
1400 "# ifdef USEDIFFUSE\n"
1401 "       // transform unnormalized light direction into tangent space\n"
1402 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1403 "       //  normalize it per pixel)\n"
1404 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1405 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1406 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1407 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1408 "# endif\n"
1409 "#endif\n"
1410 "\n"
1411 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1412 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1413 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1414 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1415 "#endif\n"
1416 "\n"
1417 "       // transform unnormalized eye direction into tangent space\n"
1418 "#ifdef USEEYEVECTOR\n"
1419 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1420 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1421 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1422 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1423 "#endif\n"
1424 "\n"
1425 "#ifdef USEFOG\n"
1426 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1427 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1428 "#endif\n"
1429 "\n"
1430 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1431 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1432 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1433 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1434 "#endif\n"
1435 "\n"
1436 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1437 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1438 "\n"
1439 "#ifdef USEREFLECTION\n"
1440 "       ModelViewProjectionPosition = gl_Position;\n"
1441 "#endif\n"
1442 "}\n"
1443 "#endif // VERTEX_SHADER\n"
1444 "\n"
1445 "\n"
1446 "\n"
1447 "\n"
1448 "#ifdef FRAGMENT_SHADER\n"
1449 "#ifdef USEDEFERREDLIGHTMAP\n"
1450 "uniform myhalf2 PixelToScreenTexCoord;\n"
1451 "uniform myhalf3 DeferredMod_Diffuse;\n"
1452 "uniform myhalf3 DeferredMod_Specular;\n"
1453 "#endif\n"
1454 "uniform myhalf3 Color_Ambient;\n"
1455 "uniform myhalf3 Color_Diffuse;\n"
1456 "uniform myhalf3 Color_Specular;\n"
1457 "uniform myhalf SpecularPower;\n"
1458 "#ifdef USEGLOW\n"
1459 "uniform myhalf3 Color_Glow;\n"
1460 "#endif\n"
1461 "uniform myhalf Alpha;\n"
1462 "#ifdef USEREFLECTION\n"
1463 "uniform vec4 DistortScaleRefractReflect;\n"
1464 "uniform vec4 ScreenScaleRefractReflect;\n"
1465 "uniform vec4 ScreenCenterRefractReflect;\n"
1466 "uniform myhalf4 ReflectColor;\n"
1467 "#endif\n"
1468 "#ifdef MODE_LIGHTDIRECTION\n"
1469 "uniform myhalf3 LightColor;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTSOURCE\n"
1472 "uniform myhalf3 LightColor;\n"
1473 "#endif\n"
1474 "void main(void)\n"
1475 "{\n"
1476 "#ifdef USEOFFSETMAPPING\n"
1477 "       // apply offsetmapping\n"
1478 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1479 "#define TexCoord TexCoordOffset\n"
1480 "#endif\n"
1481 "\n"
1482 "       // combine the diffuse textures (base, pants, shirt)\n"
1483 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1484 "#ifdef USEALPHAKILL\n"
1485 "       if (color.a < 0.5)\n"
1486 "               discard;\n"
1487 "#endif\n"
1488 "       color.a *= Alpha;\n"
1489 "#ifdef USECOLORMAPPING\n"
1490 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1491 "#endif\n"
1492 "#ifdef USEVERTEXTEXTUREBLEND\n"
1493 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1494 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1495 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1496 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1497 "       color.a = 1.0;\n"
1498 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1499 "#endif\n"
1500 "\n"
1501 "       // get the surface normal\n"
1502 "#ifdef USEVERTEXTEXTUREBLEND\n"
1503 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1504 "#else\n"
1505 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1506 "#endif\n"
1507 "\n"
1508 "       // get the material colors\n"
1509 "       myhalf3 diffusetex = color.rgb;\n"
1510 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1511 "# ifdef USEVERTEXTEXTUREBLEND\n"
1512 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1513 "# else\n"
1514 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1515 "# endif\n"
1516 "#endif\n"
1517 "\n"
1518 "\n"
1519 "\n"
1520 "\n"
1521 "#ifdef MODE_LIGHTSOURCE\n"
1522 "       // light source\n"
1523 "#ifdef USEDIFFUSE\n"
1524 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1525 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1526 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1527 "#ifdef USESPECULAR\n"
1528 "#ifdef USEEXACTSPECULARMATH\n"
1529 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1530 "#else\n"
1531 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1532 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1533 "#endif\n"
1534 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1535 "#endif\n"
1536 "#else\n"
1537 "       color.rgb = diffusetex * Color_Ambient;\n"
1538 "#endif\n"
1539 "       color.rgb *= LightColor;\n"
1540 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1541 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1542 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1543 "#endif\n"
1544 "# ifdef USECUBEFILTER\n"
1545 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1546 "# endif\n"
1547 "#endif // MODE_LIGHTSOURCE\n"
1548 "\n"
1549 "\n"
1550 "\n"
1551 "\n"
1552 "#ifdef MODE_LIGHTDIRECTION\n"
1553 "#define SHADING\n"
1554 "#ifdef USEDIFFUSE\n"
1555 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1556 "#endif\n"
1557 "#define lightcolor LightColor\n"
1558 "#endif // MODE_LIGHTDIRECTION\n"
1559 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1560 "#define SHADING\n"
1561 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1562 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1563 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1564 "       // convert modelspace light vector to tangentspace\n"
1565 "       myhalf3 lightnormal;\n"
1566 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1567 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1568 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1569 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1570 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1571 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1572 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1573 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1574 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1575 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1576 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1577 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1578 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1579 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1580 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1581 "#define SHADING\n"
1582 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1583 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1584 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1585 "#endif\n"
1586 "\n"
1587 "\n"
1588 "\n"
1589 "\n"
1590 "#ifdef MODE_LIGHTMAP\n"
1591 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1592 "#endif // MODE_LIGHTMAP\n"
1593 "#ifdef MODE_VERTEXCOLOR\n"
1594 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1595 "#endif // MODE_VERTEXCOLOR\n"
1596 "#ifdef MODE_FLATCOLOR\n"
1597 "       color.rgb = diffusetex * Color_Ambient;\n"
1598 "#endif // MODE_FLATCOLOR\n"
1599 "\n"
1600 "\n"
1601 "\n"
1602 "\n"
1603 "#ifdef SHADING\n"
1604 "# ifdef USEDIFFUSE\n"
1605 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1606 "#  ifdef USESPECULAR\n"
1607 "#   ifdef USEEXACTSPECULARMATH\n"
1608 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1609 "#   else\n"
1610 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1611 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1612 "#   endif\n"
1613 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1614 "#  else\n"
1615 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1616 "#  endif\n"
1617 "# else\n"
1618 "       color.rgb = diffusetex * Color_Ambient;\n"
1619 "# endif\n"
1620 "#endif\n"
1621 "\n"
1622 "#ifdef USEDEFERREDLIGHTMAP\n"
1623 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1624 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1625 "       color.rgb += glosstex * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1626 "#endif\n"
1627 "\n"
1628 "#ifdef USEGLOW\n"
1629 "#ifdef USEVERTEXTEXTUREBLEND\n"
1630 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1631 "#else\n"
1632 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1633 "#endif\n"
1634 "#endif\n"
1635 "\n"
1636 "#ifdef USEFOG\n"
1637 "#ifdef MODE_LIGHTSOURCE\n"
1638 "       color.rgb *= myhalf(FogVertex());\n"
1639 "#else\n"
1640 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1641 "#endif\n"
1642 "#endif\n"
1643 "\n"
1644 "       // 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"
1645 "#ifdef USEREFLECTION\n"
1646 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1647 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1648 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1649 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1650 "       // FIXME temporary hack to detect the case that the reflection\n"
1651 "       // gets blackened at edges due to leaving the area that contains actual\n"
1652 "       // content.\n"
1653 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1654 "       // 'appening.\n"
1655 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1656 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1657 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1658 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1659 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1660 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1661 "#endif\n"
1662 "\n"
1663 "       gl_FragColor = vec4(color);\n"
1664 "}\n"
1665 "#endif // FRAGMENT_SHADER\n"
1666 "\n"
1667 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1668 "#endif // !MODE_DEFERREDGEOMETRY\n"
1669 "#endif // !MODE_WATER\n"
1670 "#endif // !MODE_REFRACTION\n"
1671 "#endif // !MODE_BLOOMBLUR\n"
1672 "#endif // !MODE_GENERIC\n"
1673 "#endif // !MODE_POSTPROCESS\n"
1674 "#endif // !MODE_SHOWDEPTH\n"
1675 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1676 ;
1677
1678 /*
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 const char *builtincgshaderstring =
1707 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1708 "// written by Forest 'LordHavoc' Hale\n"
1709 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1710 "\n"
1711 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1712 "# define USEFOG\n"
1713 "#endif\n"
1714 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1715 "#define USELIGHTMAP\n"
1716 "#endif\n"
1717 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1718 "#define USEEYEVECTOR\n"
1719 "#endif\n"
1720 "\n"
1721 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1722 "#ifdef VERTEX_SHADER\n"
1723 "void main\n"
1724 "(\n"
1725 "float4 gl_Vertex : POSITION,\n"
1726 "uniform float4x4 ModelViewProjectionMatrix,\n"
1727 "out float4 gl_Position : POSITION\n"
1728 ")\n"
1729 "{\n"
1730 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1731 "}\n"
1732 "#endif\n"
1733 "#else // !MODE_DEPTH_ORSHADOW\n"
1734 "\n"
1735 "\n"
1736 "\n"
1737 "\n"
1738 "#ifdef MODE_SHOWDEPTH\n"
1739 "#ifdef VERTEX_SHADER\n"
1740 "void main\n"
1741 "(\n"
1742 "float4 gl_Vertex : POSITION,\n"
1743 "uniform float4x4 ModelViewProjectionMatrix,\n"
1744 "out float4 gl_Position : POSITION,\n"
1745 "out float4 gl_FrontColor : COLOR0\n"
1746 ")\n"
1747 "{\n"
1748 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1749 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1750 "}\n"
1751 "#endif\n"
1752 "\n"
1753 "#ifdef FRAGMENT_SHADER\n"
1754 "void main\n"
1755 "(\n"
1756 "float4 gl_FrontColor : COLOR0,\n"
1757 "out float4 gl_FragColor : COLOR\n"
1758 ")\n"
1759 "{\n"
1760 "       gl_FragColor = gl_FrontColor;\n"
1761 "}\n"
1762 "#endif\n"
1763 "#else // !MODE_SHOWDEPTH\n"
1764 "\n"
1765 "\n"
1766 "\n"
1767 "\n"
1768 "#ifdef MODE_POSTPROCESS\n"
1769 "\n"
1770 "#ifdef VERTEX_SHADER\n"
1771 "void main\n"
1772 "(\n"
1773 "float4 gl_Vertex : POSITION,\n"
1774 "uniform float4x4 ModelViewProjectionMatrix,\n"
1775 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1776 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1777 "out float4 gl_Position : POSITION,\n"
1778 "out float2 TexCoord1 : TEXCOORD0,\n"
1779 "out float2 TexCoord2 : TEXCOORD1\n"
1780 ")\n"
1781 "{\n"
1782 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1783 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1784 "#ifdef USEBLOOM\n"
1785 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1786 "#endif\n"
1787 "}\n"
1788 "#endif\n"
1789 "\n"
1790 "#ifdef FRAGMENT_SHADER\n"
1791 "void main\n"
1792 "(\n"
1793 "float2 TexCoord1 : TEXCOORD0,\n"
1794 "float2 TexCoord2 : TEXCOORD1,\n"
1795 "uniform sampler2D Texture_First,\n"
1796 "#ifdef USEBLOOM\n"
1797 "uniform sampler2D Texture_Second,\n"
1798 "#endif\n"
1799 "#ifdef USEGAMMARAMPS\n"
1800 "uniform sampler2D Texture_GammaRamps,\n"
1801 "#endif\n"
1802 "#ifdef USESATURATION\n"
1803 "uniform float Saturation,\n"
1804 "#endif\n"
1805 "#ifdef USEVIEWTINT\n"
1806 "uniform float4 ViewTintColor,\n"
1807 "#endif\n"
1808 "uniform float4 UserVec1,\n"
1809 "uniform float4 UserVec2,\n"
1810 "uniform float4 UserVec3,\n"
1811 "uniform float4 UserVec4,\n"
1812 "uniform float ClientTime,\n"
1813 "uniform float2 PixelSize,\n"
1814 "out float4 gl_FragColor : COLOR\n"
1815 ")\n"
1816 "{\n"
1817 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1818 "#ifdef USEBLOOM\n"
1819 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1820 "#endif\n"
1821 "#ifdef USEVIEWTINT\n"
1822 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1823 "#endif\n"
1824 "\n"
1825 "#ifdef USEPOSTPROCESSING\n"
1826 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1827 "// 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"
1828 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1829 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1830 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1831 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1832 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1833 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1834 "#endif\n"
1835 "\n"
1836 "#ifdef USESATURATION\n"
1837 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1838 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1839 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1840 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1841 "#endif\n"
1842 "\n"
1843 "#ifdef USEGAMMARAMPS\n"
1844 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1845 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1846 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1847 "#endif\n"
1848 "}\n"
1849 "#endif\n"
1850 "#else // !MODE_POSTPROCESS\n"
1851 "\n"
1852 "\n"
1853 "\n"
1854 "\n"
1855 "#ifdef MODE_GENERIC\n"
1856 "#ifdef VERTEX_SHADER\n"
1857 "void main\n"
1858 "(\n"
1859 "float4 gl_Vertex : POSITION,\n"
1860 "uniform float4x4 ModelViewProjectionMatrix,\n"
1861 "float4 gl_Color : COLOR0,\n"
1862 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1863 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1864 "out float4 gl_Position : POSITION,\n"
1865 "out float4 gl_FrontColor : COLOR,\n"
1866 "out float2 TexCoord1 : TEXCOORD0,\n"
1867 "out float2 TexCoord2 : TEXCOORD1\n"
1868 ")\n"
1869 "{\n"
1870 "       gl_FrontColor = gl_Color;\n"
1871 "#ifdef USEDIFFUSE\n"
1872 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1873 "#endif\n"
1874 "#ifdef USESPECULAR\n"
1875 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1876 "#endif\n"
1877 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1878 "}\n"
1879 "#endif\n"
1880 "\n"
1881 "#ifdef FRAGMENT_SHADER\n"
1882 "\n"
1883 "void main\n"
1884 "(\n"
1885 "float4 gl_FrontColor : COLOR,\n"
1886 "float2 TexCoord1 : TEXCOORD0,\n"
1887 "float2 TexCoord2 : TEXCOORD1,\n"
1888 "#ifdef USEDIFFUSE\n"
1889 "uniform sampler2D Texture_First,\n"
1890 "#endif\n"
1891 "#ifdef USESPECULAR\n"
1892 "uniform sampler2D Texture_Second,\n"
1893 "#endif\n"
1894 "out float4 gl_FragColor : COLOR\n"
1895 ")\n"
1896 "{\n"
1897 "       gl_FragColor = gl_FrontColor;\n"
1898 "#ifdef USEDIFFUSE\n"
1899 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1900 "#endif\n"
1901 "\n"
1902 "#ifdef USESPECULAR\n"
1903 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1904 "# ifdef USECOLORMAPPING\n"
1905 "       gl_FragColor *= tex2;\n"
1906 "# endif\n"
1907 "# ifdef USEGLOW\n"
1908 "       gl_FragColor += tex2;\n"
1909 "# endif\n"
1910 "# ifdef USEVERTEXTEXTUREBLEND\n"
1911 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1912 "# endif\n"
1913 "#endif\n"
1914 "}\n"
1915 "#endif\n"
1916 "#else // !MODE_GENERIC\n"
1917 "\n"
1918 "\n"
1919 "\n"
1920 "\n"
1921 "#ifdef MODE_BLOOMBLUR\n"
1922 "#ifdef VERTEX_SHADER\n"
1923 "void main\n"
1924 "(\n"
1925 "float4 gl_Vertex : POSITION,\n"
1926 "uniform float4x4 ModelViewProjectionMatrix,\n"
1927 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1928 "out float4 gl_Position : POSITION,\n"
1929 "out float2 TexCoord : TEXCOORD0\n"
1930 ")\n"
1931 "{\n"
1932 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1933 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1934 "}\n"
1935 "#endif\n"
1936 "\n"
1937 "#ifdef FRAGMENT_SHADER\n"
1938 "\n"
1939 "void main\n"
1940 "(\n"
1941 "float2 TexCoord : TEXCOORD0,\n"
1942 "uniform sampler2D Texture_First,\n"
1943 "uniform float4 BloomBlur_Parameters,\n"
1944 "out float4 gl_FragColor : COLOR\n"
1945 ")\n"
1946 "{\n"
1947 "       int i;\n"
1948 "       float2 tc = TexCoord;\n"
1949 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1950 "       tc += BloomBlur_Parameters.xy;\n"
1951 "       for (i = 1;i < SAMPLES;i++)\n"
1952 "       {\n"
1953 "               color += tex2D(Texture_First, tc).rgb;\n"
1954 "               tc += BloomBlur_Parameters.xy;\n"
1955 "       }\n"
1956 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1957 "}\n"
1958 "#endif\n"
1959 "#else // !MODE_BLOOMBLUR\n"
1960 "#ifdef MODE_REFRACTION\n"
1961 "#ifdef VERTEX_SHADER\n"
1962 "void main\n"
1963 "(\n"
1964 "float4 gl_Vertex : POSITION,\n"
1965 "uniform float4x4 ModelViewProjectionMatrix,\n"
1966 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1967 "uniform float4x4 TexMatrix,\n"
1968 "uniform float3 EyePosition,\n"
1969 "out float4 gl_Position : POSITION,\n"
1970 "out float2 TexCoord : TEXCOORD0,\n"
1971 "out float3 EyeVector : TEXCOORD1,\n"
1972 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1973 ")\n"
1974 "{\n"
1975 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1976 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1977 "       ModelViewProjectionPosition = gl_Position;\n"
1978 "}\n"
1979 "#endif\n"
1980 "\n"
1981 "#ifdef FRAGMENT_SHADER\n"
1982 "void main\n"
1983 "(\n"
1984 "float2 TexCoord : TEXCOORD0,\n"
1985 "float3 EyeVector : TEXCOORD1,\n"
1986 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1987 "uniform sampler2D Texture_Normal,\n"
1988 "uniform sampler2D Texture_Refraction,\n"
1989 "uniform sampler2D Texture_Reflection,\n"
1990 "uniform float4 DistortScaleRefractReflect,\n"
1991 "uniform float4 ScreenScaleRefractReflect,\n"
1992 "uniform float4 ScreenCenterRefractReflect,\n"
1993 "uniform float4 RefractColor,\n"
1994 "out float4 gl_FragColor : COLOR\n"
1995 ")\n"
1996 "{\n"
1997 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1998 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1999 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2000 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2001 "       // FIXME temporary hack to detect the case that the reflection\n"
2002 "       // gets blackened at edges due to leaving the area that contains actual\n"
2003 "       // content.\n"
2004 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2005 "       // 'appening.\n"
2006 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2007 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2008 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2009 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2010 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2011 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2012 "}\n"
2013 "#endif\n"
2014 "#else // !MODE_REFRACTION\n"
2015 "\n"
2016 "\n"
2017 "\n"
2018 "\n"
2019 "#ifdef MODE_WATER\n"
2020 "#ifdef VERTEX_SHADER\n"
2021 "\n"
2022 "void main\n"
2023 "(\n"
2024 "float4 gl_Vertex : POSITION,\n"
2025 "uniform float4x4 ModelViewProjectionMatrix,\n"
2026 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2027 "uniform float4x4 TexMatrix,\n"
2028 "uniform float3 EyePosition,\n"
2029 "out float4 gl_Position : POSITION,\n"
2030 "out float2 TexCoord : TEXCOORD0,\n"
2031 "out float3 EyeVector : TEXCOORD1,\n"
2032 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2033 ")\n"
2034 "{\n"
2035 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2036 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2037 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2038 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2039 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2040 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2041 "       ModelViewProjectionPosition = gl_Position;\n"
2042 "}\n"
2043 "#endif\n"
2044 "\n"
2045 "#ifdef FRAGMENT_SHADER\n"
2046 "void main\n"
2047 "(\n"
2048 "float2 TexCoord : TEXCOORD0,\n"
2049 "float3 EyeVector : TEXCOORD1,\n"
2050 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2051 "uniform sampler2D Texture_Normal,\n"
2052 "uniform sampler2D Texture_Refraction,\n"
2053 "uniform sampler2D Texture_Reflection,\n"
2054 "uniform float4 DistortScaleRefractReflect,\n"
2055 "uniform float4 ScreenScaleRefractReflect,\n"
2056 "uniform float4 ScreenCenterRefractReflect,\n"
2057 "uniform float4 RefractColor,\n"
2058 "uniform float4 ReflectColor,\n"
2059 "uniform float ReflectFactor,\n"
2060 "uniform float ReflectOffset,\n"
2061 "out float4 gl_FragColor : COLOR\n"
2062 ")\n"
2063 "{\n"
2064 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2065 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2066 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2067 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2068 "       // FIXME temporary hack to detect the case that the reflection\n"
2069 "       // gets blackened at edges due to leaving the area that contains actual\n"
2070 "       // content.\n"
2071 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2072 "       // 'appening.\n"
2073 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2074 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2075 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2076 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2077 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2078 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2079 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2080 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2081 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2082 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2083 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2084 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2085 "}\n"
2086 "#endif\n"
2087 "#else // !MODE_WATER\n"
2088 "\n"
2089 "\n"
2090 "\n"
2091 "\n"
2092 "// 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"
2093 "\n"
2094 "// fragment shader specific:\n"
2095 "#ifdef FRAGMENT_SHADER\n"
2096 "\n"
2097 "#ifdef USEFOG\n"
2098 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2099 "{\n"
2100 "       float fogfrac;\n"
2101 "#ifdef USEFOGOUTSIDE\n"
2102 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2103 "#else\n"
2104 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2105 "#endif\n"
2106 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2107 "}\n"
2108 "#endif\n"
2109 "\n"
2110 "#ifdef USEOFFSETMAPPING\n"
2111 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2112 "{\n"
2113 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2114 "       // 14 sample relief mapping: linear search and then binary search\n"
2115 "       // this basically steps forward a small amount repeatedly until it finds\n"
2116 "       // itself inside solid, then jitters forward and back using decreasing\n"
2117 "       // amounts to find the impact\n"
2118 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2119 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2120 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2121 "       float3 RT = float3(TexCoord, 1);\n"
2122 "       OffsetVector *= 0.1;\n"
2123 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2124 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2125 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\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)          - 0.5);\n"
2133 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2134 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2135 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2136 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2137 "       return RT.xy;\n"
2138 "#else\n"
2139 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2140 "       // this basically moves forward the full distance, and then backs up based\n"
2141 "       // on height of samples\n"
2142 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2143 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2144 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2145 "       TexCoord += OffsetVector;\n"
2146 "       OffsetVector *= 0.333;\n"
2147 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2148 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2149 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2150 "       return TexCoord;\n"
2151 "#endif\n"
2152 "}\n"
2153 "#endif // USEOFFSETMAPPING\n"
2154 "\n"
2155 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2156 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2157 "# ifndef USESHADOWMAPVSDCT\n"
2158 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2159 "{\n"
2160 "       float3 adir = abs(dir);\n"
2161 "       float2 tc;\n"
2162 "       float2 offset;\n"
2163 "       float ma;\n"
2164 "       if (adir.x > adir.y)\n"
2165 "       {\n"
2166 "               if (adir.x > adir.z) // X\n"
2167 "               {\n"
2168 "                       ma = adir.x;\n"
2169 "                       tc = dir.zy;\n"
2170 "                       offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2171 "               }\n"
2172 "               else // Z\n"
2173 "               {\n"
2174 "                       ma = adir.z;\n"
2175 "                       tc = dir.xy;\n"
2176 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2177 "               }\n"
2178 "       }\n"
2179 "       else\n"
2180 "       {\n"
2181 "               if (adir.y > adir.z) // Y\n"
2182 "               {\n"
2183 "                       ma = adir.y;\n"
2184 "                       tc = dir.xz;\n"
2185 "                       offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2186 "               }\n"
2187 "               else // Z\n"
2188 "               {\n"
2189 "                       ma = adir.z;\n"
2190 "                       tc = dir.xy;\n"
2191 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2192 "               }\n"
2193 "       }\n"
2194 "\n"
2195 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2196 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2197 "       stc.z += ShadowMap_Parameters.z;\n"
2198 "       return stc;\n"
2199 "}\n"
2200 "# else\n"
2201 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2202 "{\n"
2203 "       float3 adir = abs(dir);\n"
2204 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2205 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2206 "       float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2207 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2208 "       stc.z += ShadowMap_Parameters.z;\n"
2209 "       return stc;\n"
2210 "}\n"
2211 "# endif\n"
2212 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2213 "\n"
2214 "#ifdef USESHADOWMAPCUBE\n"
2215 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2216 "{\n"
2217 "    float3 adir = abs(dir);\n"
2218 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2219 "}\n"
2220 "#endif\n"
2221 "\n"
2222 "# ifdef USESHADOWMAPRECT\n"
2223 "#ifdef USESHADOWMAPVSDCT\n"
2224 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2225 "#else\n"
2226 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2227 "#endif\n"
2228 "{\n"
2229 "#ifdef USESHADOWMAPVSDCT\n"
2230 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2231 "#else\n"
2232 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2233 "#endif\n"
2234 "       float f;\n"
2235 "#  ifdef USESHADOWSAMPLER\n"
2236 "\n"
2237 "#    ifdef USESHADOWMAPPCF\n"
2238 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2239 "    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"
2240 "#    else\n"
2241 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2242 "#    endif\n"
2243 "\n"
2244 "#  else\n"
2245 "\n"
2246 "#    ifdef USESHADOWMAPPCF\n"
2247 "#      if USESHADOWMAPPCF > 1\n"
2248 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2249 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2250 "    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"
2251 "    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"
2252 "    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"
2253 "    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"
2254 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2255 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2256 "#      else\n"
2257 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2258 "    float2 offset = frac(shadowmaptc.xy);\n"
2259 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2260 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2261 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2262 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2263 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2264 "#      endif\n"
2265 "#    else\n"
2266 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2267 "#    endif\n"
2268 "\n"
2269 "#  endif\n"
2270 "       return f;\n"
2271 "}\n"
2272 "# endif\n"
2273 "\n"
2274 "# ifdef USESHADOWMAP2D\n"
2275 "#ifdef USESHADOWMAPVSDCT\n"
2276 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2277 "#else\n"
2278 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2279 "#endif\n"
2280 "{\n"
2281 "#ifdef USESHADOWMAPVSDCT\n"
2282 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2283 "#else\n"
2284 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2285 "#endif\n"
2286 "    float f;\n"
2287 "\n"
2288 "#  ifdef USESHADOWSAMPLER\n"
2289 "#    ifdef USESHADOWMAPPCF\n"
2290 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2291 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2292 "    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"
2293 "#    else\n"
2294 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2295 "#    endif\n"
2296 "#  else\n"
2297 "#    ifdef USESHADOWMAPPCF\n"
2298 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2299 "#      ifdef GL_ARB_texture_gather\n"
2300 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2301 "#      else\n"
2302 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2303 "#      endif\n"
2304 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2305 "    center *= ShadowMap_TextureScale;\n"
2306 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2307 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2308 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2309 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2310 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2311 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2312 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2313 "#     else\n"
2314 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2315 "#      if USESHADOWMAPPCF > 1\n"
2316 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2317 "    center *= ShadowMap_TextureScale;\n"
2318 "    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"
2319 "    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"
2320 "    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"
2321 "    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"
2322 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2323 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2324 "#      else\n"
2325 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2326 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2327 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2328 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2329 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2330 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2331 "#      endif\n"
2332 "#     endif\n"
2333 "#    else\n"
2334 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2335 "#    endif\n"
2336 "#  endif\n"
2337 "    return f;\n"
2338 "}\n"
2339 "# endif\n"
2340 "\n"
2341 "# ifdef USESHADOWMAPCUBE\n"
2342 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2343 "{\n"
2344 "    // apply depth texture cubemap as light filter\n"
2345 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2346 "    float f;\n"
2347 "#  ifdef USESHADOWSAMPLER\n"
2348 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2349 "#  else\n"
2350 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2351 "#  endif\n"
2352 "    return f;\n"
2353 "}\n"
2354 "# endif\n"
2355 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2356 "#endif // FRAGMENT_SHADER\n"
2357 "\n"
2358 "\n"
2359 "\n"
2360 "\n"
2361 "#ifdef MODE_DEFERREDGEOMETRY\n"
2362 "#ifdef VERTEX_SHADER\n"
2363 "void main\n"
2364 "(\n"
2365 "float4 gl_Vertex : POSITION,\n"
2366 "uniform float4x4 ModelViewProjectionMatrix,\n"
2367 "#ifdef USEVERTEXTEXTUREBLEND\n"
2368 "float4 gl_Color : COLOR0,\n"
2369 "#endif\n"
2370 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2371 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2372 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2373 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2374 "uniform float4x4 TexMatrix,\n"
2375 "#ifdef USEVERTEXTEXTUREBLEND\n"
2376 "uniform float4x4 BackgroundTexMatrix,\n"
2377 "#endif\n"
2378 "uniform float4x4 ModelViewMatrix,\n"
2379 "#ifdef USEOFFSETMAPPING\n"
2380 "uniform float3 EyePosition,\n"
2381 "#endif\n"
2382 "out float4 gl_Position : POSITION,\n"
2383 "out float4 gl_FrontColor : COLOR,\n"
2384 "out float4 TexCoordBoth : TEXCOORD0,\n"
2385 "#ifdef USEOFFSETMAPPING\n"
2386 "out float3 EyeVector : TEXCOORD2,\n"
2387 "#endif\n"
2388 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2389 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2390 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2391 ")\n"
2392 "{\n"
2393 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2394 "#ifdef USEVERTEXTEXTUREBLEND\n"
2395 "       gl_FrontColor = gl_Color;\n"
2396 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2397 "#endif\n"
2398 "\n"
2399 "       // transform unnormalized eye direction into tangent space\n"
2400 "#ifdef USEOFFSETMAPPING\n"
2401 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2402 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2403 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2404 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2405 "#endif\n"
2406 "\n"
2407 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2408 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2409 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2410 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2411 "}\n"
2412 "#endif // VERTEX_SHADER\n"
2413 "\n"
2414 "#ifdef FRAGMENT_SHADER\n"
2415 "void main\n"
2416 "(\n"
2417 "float4 TexCoordBoth : TEXCOORD0,\n"
2418 "float3 EyeVector : TEXCOORD2,\n"
2419 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2420 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2421 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2422 "uniform sampler2D Texture_Normal,\n"
2423 "#ifdef USEALPHAKILL\n"
2424 "uniform sampler2D Texture_Color,\n"
2425 "#endif\n"
2426 "#ifdef USEVERTEXTEXTUREBLEND\n"
2427 "uniform sampler2D Texture_SecondaryNormal,\n"
2428 "#endif\n"
2429 "#ifdef USEOFFSETMAPPING\n"
2430 "uniform float OffsetMapping_Scale,\n"
2431 "#endif\n"
2432 "uniform half SpecularPower,\n"
2433 "out float4 gl_FragColor : COLOR\n"
2434 ")\n"
2435 "{\n"
2436 "       float2 TexCoord = TexCoordBoth.xy;\n"
2437 "#ifdef USEOFFSETMAPPING\n"
2438 "       // apply offsetmapping\n"
2439 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2440 "#define TexCoord TexCoordOffset\n"
2441 "#endif\n"
2442 "\n"
2443 "#ifdef USEALPHAKILL\n"
2444 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2445 "               discard;\n"
2446 "#endif\n"
2447 "\n"
2448 "#ifdef USEVERTEXTEXTUREBLEND\n"
2449 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2450 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2451 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2452 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2453 "#endif\n"
2454 "\n"
2455 "#ifdef USEVERTEXTEXTUREBLEND\n"
2456 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2457 "#else\n"
2458 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2459 "#endif\n"
2460 "\n"
2461 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2462 "}\n"
2463 "#endif // FRAGMENT_SHADER\n"
2464 "#else // !MODE_DEFERREDGEOMETRY\n"
2465 "\n"
2466 "\n"
2467 "\n"
2468 "\n"
2469 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2470 "#ifdef VERTEX_SHADER\n"
2471 "void main\n"
2472 "(\n"
2473 "float4 gl_Vertex : POSITION,\n"
2474 "uniform float4x4 ModelViewProjectionMatrix,\n"
2475 "uniform float4x4 ModelViewMatrix,\n"
2476 "out float4 gl_Position : POSITION,\n"
2477 "out float4 ModelViewPosition : TEXCOORD0\n"
2478 ")\n"
2479 "{\n"
2480 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2481 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2482 "}\n"
2483 "#endif // VERTEX_SHADER\n"
2484 "\n"
2485 "#ifdef FRAGMENT_SHADER\n"
2486 "void main\n"
2487 "(\n"
2488 "float2 Pixel : WPOS,\n"
2489 "float4 ModelViewPosition : TEXCOORD0,\n"
2490 "uniform float4x4 ViewToLight,\n"
2491 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2492 "uniform float3 LightPosition,\n"
2493 "uniform half2 PixelToScreenTexCoord,\n"
2494 "uniform half3 DeferredColor_Ambient,\n"
2495 "uniform half3 DeferredColor_Diffuse,\n"
2496 "#ifdef USESPECULAR\n"
2497 "uniform half3 DeferredColor_Specular,\n"
2498 "uniform half SpecularPower,\n"
2499 "#endif\n"
2500 "uniform sampler2D Texture_Attenuation,\n"
2501 "uniform sampler2D Texture_ScreenDepth,\n"
2502 "uniform sampler2D Texture_ScreenNormalMap,\n"
2503 "\n"
2504 "#ifdef USESHADOWMAPRECT\n"
2505 "# ifdef USESHADOWSAMPLER\n"
2506 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2507 "# else\n"
2508 "uniform samplerRECT Texture_ShadowMapRect,\n"
2509 "# endif\n"
2510 "#endif\n"
2511 "\n"
2512 "#ifdef USESHADOWMAP2D\n"
2513 "# ifdef USESHADOWSAMPLER\n"
2514 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2515 "# else\n"
2516 "uniform sampler2D Texture_ShadowMap2D,\n"
2517 "# endif\n"
2518 "#endif\n"
2519 "\n"
2520 "#ifdef USESHADOWMAPVSDCT\n"
2521 "uniform samplerCUBE Texture_CubeProjection,\n"
2522 "#endif\n"
2523 "\n"
2524 "#ifdef USESHADOWMAPCUBE\n"
2525 "# ifdef USESHADOWSAMPLER\n"
2526 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2527 "# else\n"
2528 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2529 "# endif\n"
2530 "#endif\n"
2531 "\n"
2532 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2533 "uniform float2 ShadowMap_TextureScale,\n"
2534 "uniform float4 ShadowMap_Parameters,\n"
2535 "#endif\n"
2536 "\n"
2537 "out float4 gl_FragData0 : COLOR0,\n"
2538 "out float4 gl_FragData1 : COLOR1\n"
2539 ")\n"
2540 "{\n"
2541 "       // calculate viewspace pixel position\n"
2542 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2543 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2544 "       float3 position;\n"
2545 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2546 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2547 "       // decode viewspace pixel normal\n"
2548 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2549 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2550 "       // surfacenormal = pixel normal in viewspace\n"
2551 "       // LightVector = pixel to light in viewspace\n"
2552 "       // CubeVector = position in lightspace\n"
2553 "       // eyevector = pixel to view in viewspace\n"
2554 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2555 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2556 "#ifdef USEDIFFUSE\n"
2557 "       // calculate diffuse shading\n"
2558 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2559 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2560 "#endif\n"
2561 "#ifdef USESPECULAR\n"
2562 "       // calculate directional shading\n"
2563 "       float3 eyevector = position * -1.0;\n"
2564 "#  ifdef USEEXACTSPECULARMATH\n"
2565 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2566 "#  else\n"
2567 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2568 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2569 "#  endif\n"
2570 "#endif\n"
2571 "\n"
2572 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2573 "       fade *= ShadowMapCompare(CubeVector,\n"
2574 "# if defined(USESHADOWMAP2D)\n"
2575 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2576 "# endif\n"
2577 "# if defined(USESHADOWMAPRECT)\n"
2578 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2579 "# endif\n"
2580 "# if defined(USESHADOWMAPCUBE)\n"
2581 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2582 "# endif\n"
2583 "\n"
2584 "#ifdef USESHADOWMAPVSDCT\n"
2585 ", Texture_CubeProjection\n"
2586 "#endif\n"
2587 "       );\n"
2588 "#endif\n"
2589 "\n"
2590 "#ifdef USEDIFFUSE\n"
2591 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2592 "#else\n"
2593 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2594 "#endif\n"
2595 "#ifdef USESPECULAR\n"
2596 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2597 "#else\n"
2598 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2599 "#endif\n"
2600 "\n"
2601 "# ifdef USECUBEFILTER\n"
2602 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2603 "       gl_FragData0.rgb *= cubecolor;\n"
2604 "       gl_FragData1.rgb *= cubecolor;\n"
2605 "# endif\n"
2606 "}\n"
2607 "#endif // FRAGMENT_SHADER\n"
2608 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2609 "\n"
2610 "\n"
2611 "\n"
2612 "\n"
2613 "#ifdef VERTEX_SHADER\n"
2614 "void main\n"
2615 "(\n"
2616 "float4 gl_Vertex : POSITION,\n"
2617 "uniform float4x4 ModelViewProjectionMatrix,\n"
2618 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2619 "float4 gl_Color : COLOR0,\n"
2620 "#endif\n"
2621 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2622 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2623 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2624 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2625 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2626 "\n"
2627 "uniform float3 EyePosition,\n"
2628 "uniform float4x4 TexMatrix,\n"
2629 "#ifdef USEVERTEXTEXTUREBLEND\n"
2630 "uniform float4x4 BackgroundTexMatrix,\n"
2631 "#endif\n"
2632 "#ifdef MODE_LIGHTSOURCE\n"
2633 "uniform float4x4 ModelToLight,\n"
2634 "#endif\n"
2635 "#ifdef MODE_LIGHTSOURCE\n"
2636 "uniform float3 LightPosition,\n"
2637 "#endif\n"
2638 "#ifdef MODE_LIGHTDIRECTION\n"
2639 "uniform float3 LightDir,\n"
2640 "#endif\n"
2641 "uniform float4 FogPlane,\n"
2642 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2643 "uniform float3 LightPosition,\n"
2644 "#endif\n"
2645 "\n"
2646 "out float4 gl_FrontColor : COLOR,\n"
2647 "out float4 TexCoordBoth : TEXCOORD0,\n"
2648 "#ifdef USELIGHTMAP\n"
2649 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2650 "#endif\n"
2651 "#ifdef USEEYEVECTOR\n"
2652 "out float3 EyeVector : TEXCOORD2,\n"
2653 "#endif\n"
2654 "#ifdef USEREFLECTION\n"
2655 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2656 "#endif\n"
2657 "#ifdef USEFOG\n"
2658 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2659 "#endif\n"
2660 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2661 "out float3 LightVector : TEXCOORD5,\n"
2662 "#endif\n"
2663 "#ifdef MODE_LIGHTSOURCE\n"
2664 "out float3 CubeVector : TEXCOORD3,\n"
2665 "#endif\n"
2666 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2667 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2668 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2669 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2670 "#endif\n"
2671 "out float4 gl_Position : POSITION\n"
2672 ")\n"
2673 "{\n"
2674 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2675 "       gl_FrontColor = gl_Color;\n"
2676 "#endif\n"
2677 "       // copy the surface texcoord\n"
2678 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2679 "#ifdef USEVERTEXTEXTUREBLEND\n"
2680 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2681 "#endif\n"
2682 "#ifdef USELIGHTMAP\n"
2683 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2684 "#endif\n"
2685 "\n"
2686 "#ifdef MODE_LIGHTSOURCE\n"
2687 "       // transform vertex position into light attenuation/cubemap space\n"
2688 "       // (-1 to +1 across the light box)\n"
2689 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2690 "\n"
2691 "# ifdef USEDIFFUSE\n"
2692 "       // transform unnormalized light direction into tangent space\n"
2693 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2694 "       //  normalize it per pixel)\n"
2695 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2696 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2697 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2698 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2699 "# endif\n"
2700 "#endif\n"
2701 "\n"
2702 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2703 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2704 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2705 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2706 "#endif\n"
2707 "\n"
2708 "       // transform unnormalized eye direction into tangent space\n"
2709 "#ifdef USEEYEVECTOR\n"
2710 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2711 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2712 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2713 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2714 "#endif\n"
2715 "\n"
2716 "#ifdef USEFOG\n"
2717 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2718 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2719 "#endif\n"
2720 "\n"
2721 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2722 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2723 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2724 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2725 "#endif\n"
2726 "\n"
2727 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2728 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2729 "\n"
2730 "#ifdef USEREFLECTION\n"
2731 "       ModelViewProjectionPosition = gl_Position;\n"
2732 "#endif\n"
2733 "}\n"
2734 "#endif // VERTEX_SHADER\n"
2735 "\n"
2736 "\n"
2737 "\n"
2738 "\n"
2739 "#ifdef FRAGMENT_SHADER\n"
2740 "void main\n"
2741 "(\n"
2742 "#ifdef USEDEFERREDLIGHTMAP\n"
2743 "float2 Pixel : WPOS,\n"
2744 "#endif\n"
2745 "float4 gl_FrontColor : COLOR,\n"
2746 "float4 TexCoordBoth : TEXCOORD0,\n"
2747 "#ifdef USELIGHTMAP\n"
2748 "float2 TexCoordLightmap : TEXCOORD1,\n"
2749 "#endif\n"
2750 "#ifdef USEEYEVECTOR\n"
2751 "float3 EyeVector : TEXCOORD2,\n"
2752 "#endif\n"
2753 "#ifdef USEREFLECTION\n"
2754 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2755 "#endif\n"
2756 "#ifdef USEFOG\n"
2757 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2758 "#endif\n"
2759 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2760 "float3 LightVector : TEXCOORD5,\n"
2761 "#endif\n"
2762 "#ifdef MODE_LIGHTSOURCE\n"
2763 "float3 CubeVector : TEXCOORD3,\n"
2764 "#endif\n"
2765 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2766 "float4 ModelViewPosition : TEXCOORD0,\n"
2767 "#endif\n"
2768 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2769 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2770 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2771 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2772 "#endif\n"
2773 "\n"
2774 "uniform sampler2D Texture_Normal,\n"
2775 "uniform sampler2D Texture_Color,\n"
2776 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2777 "uniform sampler2D Texture_Gloss,\n"
2778 "#endif\n"
2779 "#ifdef USEGLOW\n"
2780 "uniform sampler2D Texture_Glow,\n"
2781 "#endif\n"
2782 "#ifdef USEVERTEXTEXTUREBLEND\n"
2783 "uniform sampler2D Texture_SecondaryNormal,\n"
2784 "uniform sampler2D Texture_SecondaryColor,\n"
2785 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2786 "uniform sampler2D Texture_SecondaryGloss,\n"
2787 "#endif\n"
2788 "#ifdef USEGLOW\n"
2789 "uniform sampler2D Texture_SecondaryGlow,\n"
2790 "#endif\n"
2791 "#endif\n"
2792 "#ifdef USECOLORMAPPING\n"
2793 "uniform sampler2D Texture_Pants,\n"
2794 "uniform sampler2D Texture_Shirt,\n"
2795 "#endif\n"
2796 "#ifdef USEFOG\n"
2797 "uniform sampler2D Texture_FogMask,\n"
2798 "#endif\n"
2799 "#ifdef USELIGHTMAP\n"
2800 "uniform sampler2D Texture_Lightmap,\n"
2801 "#endif\n"
2802 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2803 "uniform sampler2D Texture_Deluxemap,\n"
2804 "#endif\n"
2805 "#ifdef USEREFLECTION\n"
2806 "uniform sampler2D Texture_Reflection,\n"
2807 "#endif\n"
2808 "\n"
2809 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2810 "uniform sampler2D Texture_ScreenDepth,\n"
2811 "uniform sampler2D Texture_ScreenNormalMap,\n"
2812 "#endif\n"
2813 "#ifdef USEDEFERREDLIGHTMAP\n"
2814 "uniform sampler2D Texture_ScreenDiffuse,\n"
2815 "uniform sampler2D Texture_ScreenSpecular,\n"
2816 "#endif\n"
2817 "\n"
2818 "#ifdef USECOLORMAPPING\n"
2819 "uniform half3 Color_Pants,\n"
2820 "uniform half3 Color_Shirt,\n"
2821 "#endif\n"
2822 "#ifdef USEFOG\n"
2823 "uniform float3 FogColor,\n"
2824 "uniform float FogRangeRecip,\n"
2825 "uniform float FogPlaneViewDist,\n"
2826 "uniform float FogHeightFade,\n"
2827 "#endif\n"
2828 "\n"
2829 "#ifdef USEOFFSETMAPPING\n"
2830 "uniform float OffsetMapping_Scale,\n"
2831 "#endif\n"
2832 "\n"
2833 "#ifdef USEDEFERREDLIGHTMAP\n"
2834 "uniform half2 PixelToScreenTexCoord,\n"
2835 "uniform half3 DeferredMod_Diffuse,\n"
2836 "uniform half3 DeferredMod_Specular,\n"
2837 "#endif\n"
2838 "uniform half3 Color_Ambient,\n"
2839 "uniform half3 Color_Diffuse,\n"
2840 "uniform half3 Color_Specular,\n"
2841 "uniform half SpecularPower,\n"
2842 "#ifdef USEGLOW\n"
2843 "uniform half3 Color_Glow,\n"
2844 "#endif\n"
2845 "uniform half Alpha,\n"
2846 "#ifdef USEREFLECTION\n"
2847 "uniform float4 DistortScaleRefractReflect,\n"
2848 "uniform float4 ScreenScaleRefractReflect,\n"
2849 "uniform float4 ScreenCenterRefractReflect,\n"
2850 "uniform half4 ReflectColor,\n"
2851 "#endif\n"
2852 "#ifdef MODE_LIGHTDIRECTION\n"
2853 "uniform half3 LightColor,\n"
2854 "#endif\n"
2855 "#ifdef MODE_LIGHTSOURCE\n"
2856 "uniform half3 LightColor,\n"
2857 "#endif\n"
2858 "\n"
2859 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2860 "uniform sampler2D Texture_Attenuation,\n"
2861 "uniform samplerCUBE Texture_Cube,\n"
2862 "\n"
2863 "#ifdef USESHADOWMAPRECT\n"
2864 "# ifdef USESHADOWSAMPLER\n"
2865 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2866 "# else\n"
2867 "uniform samplerRECT Texture_ShadowMapRect,\n"
2868 "# endif\n"
2869 "#endif\n"
2870 "\n"
2871 "#ifdef USESHADOWMAP2D\n"
2872 "# ifdef USESHADOWSAMPLER\n"
2873 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2874 "# else\n"
2875 "uniform sampler2D Texture_ShadowMap2D,\n"
2876 "# endif\n"
2877 "#endif\n"
2878 "\n"
2879 "#ifdef USESHADOWMAPVSDCT\n"
2880 "uniform samplerCUBE Texture_CubeProjection,\n"
2881 "#endif\n"
2882 "\n"
2883 "#ifdef USESHADOWMAPCUBE\n"
2884 "# ifdef USESHADOWSAMPLER\n"
2885 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2886 "# else\n"
2887 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2888 "# endif\n"
2889 "#endif\n"
2890 "\n"
2891 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2892 "uniform float2 ShadowMap_TextureScale,\n"
2893 "uniform float4 ShadowMap_Parameters,\n"
2894 "#endif\n"
2895 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2896 "\n"
2897 "out float4 gl_FragColor : COLOR\n"
2898 ")\n"
2899 "{\n"
2900 "       float2 TexCoord = TexCoordBoth.xy;\n"
2901 "#ifdef USEVERTEXTEXTUREBLEND\n"
2902 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2903 "#endif\n"
2904 "#ifdef USEOFFSETMAPPING\n"
2905 "       // apply offsetmapping\n"
2906 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2907 "#define TexCoord TexCoordOffset\n"
2908 "#endif\n"
2909 "\n"
2910 "       // combine the diffuse textures (base, pants, shirt)\n"
2911 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2912 "#ifdef USEALPHAKILL\n"
2913 "       if (color.a < 0.5)\n"
2914 "               discard;\n"
2915 "#endif\n"
2916 "       color.a *= Alpha;\n"
2917 "#ifdef USECOLORMAPPING\n"
2918 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2919 "#endif\n"
2920 "#ifdef USEVERTEXTEXTUREBLEND\n"
2921 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2922 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2923 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2924 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2925 "       color.a = 1.0;\n"
2926 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2927 "#endif\n"
2928 "\n"
2929 "       // get the surface normal\n"
2930 "#ifdef USEVERTEXTEXTUREBLEND\n"
2931 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2932 "#else\n"
2933 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2934 "#endif\n"
2935 "\n"
2936 "       // get the material colors\n"
2937 "       half3 diffusetex = color.rgb;\n"
2938 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2939 "# ifdef USEVERTEXTEXTUREBLEND\n"
2940 "       half3 glosstex = half3(lerp(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2941 "# else\n"
2942 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2943 "# endif\n"
2944 "#endif\n"
2945 "\n"
2946 "\n"
2947 "\n"
2948 "\n"
2949 "#ifdef MODE_LIGHTSOURCE\n"
2950 "       // light source\n"
2951 "#ifdef USEDIFFUSE\n"
2952 "       half3 lightnormal = half3(normalize(LightVector));\n"
2953 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2954 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2955 "#ifdef USESPECULAR\n"
2956 "#ifdef USEEXACTSPECULARMATH\n"
2957 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2958 "#else\n"
2959 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2960 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2961 "#endif\n"
2962 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2963 "#endif\n"
2964 "#else\n"
2965 "       color.rgb = diffusetex * Color_Ambient;\n"
2966 "#endif\n"
2967 "       color.rgb *= LightColor;\n"
2968 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2969 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2970 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2971 "# if defined(USESHADOWMAP2D)\n"
2972 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2973 "# endif\n"
2974 "# if defined(USESHADOWMAPRECT)\n"
2975 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2976 "# endif\n"
2977 "# if defined(USESHADOWMAPCUBE)\n"
2978 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2979 "# endif\n"
2980 "\n"
2981 "#ifdef USESHADOWMAPVSDCT\n"
2982 ", Texture_CubeProjection\n"
2983 "#endif\n"
2984 "       );\n"
2985 "\n"
2986 "#endif\n"
2987 "# ifdef USECUBEFILTER\n"
2988 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2989 "# endif\n"
2990 "#endif // MODE_LIGHTSOURCE\n"
2991 "\n"
2992 "\n"
2993 "\n"
2994 "\n"
2995 "#ifdef MODE_LIGHTDIRECTION\n"
2996 "#define SHADING\n"
2997 "#ifdef USEDIFFUSE\n"
2998 "       half3 lightnormal = half3(normalize(LightVector));\n"
2999 "#endif\n"
3000 "#define lightcolor LightColor\n"
3001 "#endif // MODE_LIGHTDIRECTION\n"
3002 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3003 "#define SHADING\n"
3004 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3005 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3006 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3007 "       // convert modelspace light vector to tangentspace\n"
3008 "       half3 lightnormal;\n"
3009 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3010 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3011 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3012 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3013 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3014 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3015 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3016 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3017 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3018 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3019 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3020 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3021 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3022 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3023 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3024 "#define SHADING\n"
3025 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3026 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3027 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3028 "#endif\n"
3029 "\n"
3030 "\n"
3031 "\n"
3032 "\n"
3033 "#ifdef MODE_LIGHTMAP\n"
3034 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3035 "#endif // MODE_LIGHTMAP\n"
3036 "#ifdef MODE_VERTEXCOLOR\n"
3037 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3038 "#endif // MODE_VERTEXCOLOR\n"
3039 "#ifdef MODE_FLATCOLOR\n"
3040 "       color.rgb = diffusetex * Color_Ambient;\n"
3041 "#endif // MODE_FLATCOLOR\n"
3042 "\n"
3043 "\n"
3044 "\n"
3045 "\n"
3046 "#ifdef SHADING\n"
3047 "# ifdef USEDIFFUSE\n"
3048 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3049 "#  ifdef USESPECULAR\n"
3050 "#   ifdef USEEXACTSPECULARMATH\n"
3051 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3052 "#   else\n"
3053 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3054 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3055 "#   endif\n"
3056 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3057 "#  else\n"
3058 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3059 "#  endif\n"
3060 "# else\n"
3061 "       color.rgb = diffusetex * Color_Ambient;\n"
3062 "# endif\n"
3063 "#endif\n"
3064 "\n"
3065 "#ifdef USEDEFERREDLIGHTMAP\n"
3066 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3067 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3068 "       color.rgb += glosstex * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3069 "#endif\n"
3070 "\n"
3071 "#ifdef USEGLOW\n"
3072 "#ifdef USEVERTEXTEXTUREBLEND\n"
3073 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3074 "#else\n"
3075 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3076 "#endif\n"
3077 "#endif\n"
3078 "\n"
3079 "#ifdef USEFOG\n"
3080 "#ifdef MODE_LIGHTSOURCE\n"
3081 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3082 "#else\n"
3083 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3084 "#endif\n"
3085 "#endif\n"
3086 "\n"
3087 "       // 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"
3088 "#ifdef USEREFLECTION\n"
3089 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3090 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3091 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3092 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3093 "       // FIXME temporary hack to detect the case that the reflection\n"
3094 "       // gets blackened at edges due to leaving the area that contains actual\n"
3095 "       // content.\n"
3096 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3097 "       // 'appening.\n"
3098 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3099 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3100 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3101 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3102 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3103 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3104 "#endif\n"
3105 "\n"
3106 "       gl_FragColor = float4(color);\n"
3107 "}\n"
3108 "#endif // FRAGMENT_SHADER\n"
3109 "\n"
3110 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3111 "#endif // !MODE_DEFERREDGEOMETRY\n"
3112 "#endif // !MODE_WATER\n"
3113 "#endif // !MODE_REFRACTION\n"
3114 "#endif // !MODE_BLOOMBLUR\n"
3115 "#endif // !MODE_GENERIC\n"
3116 "#endif // !MODE_POSTPROCESS\n"
3117 "#endif // !MODE_SHOWDEPTH\n"
3118 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3119 ;
3120
3121 //=======================================================================================================================================================
3122
3123 typedef struct shaderpermutationinfo_s
3124 {
3125         const char *pretext;
3126         const char *name;
3127 }
3128 shaderpermutationinfo_t;
3129
3130 typedef struct shadermodeinfo_s
3131 {
3132         const char *vertexfilename;
3133         const char *geometryfilename;
3134         const char *fragmentfilename;
3135         const char *pretext;
3136         const char *name;
3137 }
3138 shadermodeinfo_t;
3139
3140 typedef enum shaderpermutation_e
3141 {
3142         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3143         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3144         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3145         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3146         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3147         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3148         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3149         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3150         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3151         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3152         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3153         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3154         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3155         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3156         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3157         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3158         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3159         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3160         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3161         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3162         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3163         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3164         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3165         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3166         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3167         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3168         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3169         SHADERPERMUTATION_COUNT = 26 ///< size of shaderpermutationinfo array
3170 }
3171 shaderpermutation_t;
3172
3173 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3174 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3175 {
3176         {"#define USEDIFFUSE\n", " diffuse"},
3177         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3178         {"#define USEVIEWTINT\n", " viewtint"},
3179         {"#define USECOLORMAPPING\n", " colormapping"},
3180         {"#define USESATURATION\n", " saturation"},
3181         {"#define USEFOGINSIDE\n", " foginside"},
3182         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3183         {"#define USEGAMMARAMPS\n", " gammaramps"},
3184         {"#define USECUBEFILTER\n", " cubefilter"},
3185         {"#define USEGLOW\n", " glow"},
3186         {"#define USEBLOOM\n", " bloom"},
3187         {"#define USESPECULAR\n", " specular"},
3188         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3189         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3190         {"#define USEREFLECTION\n", " reflection"},
3191         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3192         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3193         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3194         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3195         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3196         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3197         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3198         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3199         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3200         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3201         {"#define USEALPHAKILL\n", " alphakill"},
3202 };
3203
3204 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3205 typedef enum shadermode_e
3206 {
3207         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3208         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3209         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3210         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3211         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3212         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3213         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3214         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3215         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3216         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3217         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3218         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3219         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3220         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3221         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3222         SHADERMODE_COUNT
3223 }
3224 shadermode_t;
3225
3226 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3227 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3228 {
3229         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3230         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3231         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3232         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3233         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3234         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3235         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3236         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3237         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3238         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3239         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3240         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3241         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3242         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3243         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3244 };
3245
3246 #ifdef SUPPORTCG
3247 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3248 {
3249         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3250         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3251         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3252         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3253         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3254         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3255         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3256         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3257         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3258         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3259         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3260         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3261         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3262         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3263         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3264 };
3265 #endif
3266
3267 struct r_glsl_permutation_s;
3268 typedef struct r_glsl_permutation_s
3269 {
3270         /// hash lookup data
3271         struct r_glsl_permutation_s *hashnext;
3272         unsigned int mode;
3273         unsigned int permutation;
3274
3275         /// indicates if we have tried compiling this permutation already
3276         qboolean compiled;
3277         /// 0 if compilation failed
3278         int program;
3279         /// locations of detected uniforms in program object, or -1 if not found
3280         int loc_Texture_First;
3281         int loc_Texture_Second;
3282         int loc_Texture_GammaRamps;
3283         int loc_Texture_Normal;
3284         int loc_Texture_Color;
3285         int loc_Texture_Gloss;
3286         int loc_Texture_Glow;
3287         int loc_Texture_SecondaryNormal;
3288         int loc_Texture_SecondaryColor;
3289         int loc_Texture_SecondaryGloss;
3290         int loc_Texture_SecondaryGlow;
3291         int loc_Texture_Pants;
3292         int loc_Texture_Shirt;
3293         int loc_Texture_FogMask;
3294         int loc_Texture_Lightmap;
3295         int loc_Texture_Deluxemap;
3296         int loc_Texture_Attenuation;
3297         int loc_Texture_Cube;
3298         int loc_Texture_Refraction;
3299         int loc_Texture_Reflection;
3300         int loc_Texture_ShadowMapRect;
3301         int loc_Texture_ShadowMapCube;
3302         int loc_Texture_ShadowMap2D;
3303         int loc_Texture_CubeProjection;
3304         int loc_Texture_ScreenDepth;
3305         int loc_Texture_ScreenNormalMap;
3306         int loc_Texture_ScreenDiffuse;
3307         int loc_Texture_ScreenSpecular;
3308         int loc_Alpha;
3309         int loc_BloomBlur_Parameters;
3310         int loc_ClientTime;
3311         int loc_Color_Ambient;
3312         int loc_Color_Diffuse;
3313         int loc_Color_Specular;
3314         int loc_Color_Glow;
3315         int loc_Color_Pants;
3316         int loc_Color_Shirt;
3317         int loc_DeferredColor_Ambient;
3318         int loc_DeferredColor_Diffuse;
3319         int loc_DeferredColor_Specular;
3320         int loc_DeferredMod_Diffuse;
3321         int loc_DeferredMod_Specular;
3322         int loc_DistortScaleRefractReflect;
3323         int loc_EyePosition;
3324         int loc_FogColor;
3325         int loc_FogHeightFade;
3326         int loc_FogPlane;
3327         int loc_FogPlaneViewDist;
3328         int loc_FogRangeRecip;
3329         int loc_LightColor;
3330         int loc_LightDir;
3331         int loc_LightPosition;
3332         int loc_OffsetMapping_Scale;
3333         int loc_PixelSize;
3334         int loc_ReflectColor;
3335         int loc_ReflectFactor;
3336         int loc_ReflectOffset;
3337         int loc_RefractColor;
3338         int loc_Saturation;
3339         int loc_ScreenCenterRefractReflect;
3340         int loc_ScreenScaleRefractReflect;
3341         int loc_ScreenToDepth;
3342         int loc_ShadowMap_Parameters;
3343         int loc_ShadowMap_TextureScale;
3344         int loc_SpecularPower;
3345         int loc_UserVec1;
3346         int loc_UserVec2;
3347         int loc_UserVec3;
3348         int loc_UserVec4;
3349         int loc_ViewTintColor;
3350         int loc_ViewToLight;
3351         int loc_ModelToLight;
3352         int loc_TexMatrix;
3353         int loc_BackgroundTexMatrix;
3354         int loc_ModelViewProjectionMatrix;
3355         int loc_ModelViewMatrix;
3356         int loc_PixelToScreenTexCoord;
3357 }
3358 r_glsl_permutation_t;
3359
3360 #define SHADERPERMUTATION_HASHSIZE 256
3361
3362 /// information about each possible shader permutation
3363 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3364 /// currently selected permutation
3365 r_glsl_permutation_t *r_glsl_permutation;
3366 /// storage for permutations linked in the hash table
3367 memexpandablearray_t r_glsl_permutationarray;
3368
3369 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3370 {
3371         //unsigned int hashdepth = 0;
3372         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3373         r_glsl_permutation_t *p;
3374         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3375         {
3376                 if (p->mode == mode && p->permutation == permutation)
3377                 {
3378                         //if (hashdepth > 10)
3379                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3380                         return p;
3381                 }
3382                 //hashdepth++;
3383         }
3384         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3385         p->mode = mode;
3386         p->permutation = permutation;
3387         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3388         r_glsl_permutationhash[mode][hashindex] = p;
3389         //if (hashdepth > 10)
3390         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3391         return p;
3392 }
3393
3394 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3395 {
3396         char *shaderstring;
3397         if (!filename || !filename[0])
3398                 return NULL;
3399         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3400         if (shaderstring)
3401         {
3402                 if (printfromdisknotice)
3403                         Con_DPrintf("from disk %s... ", filename);
3404                 return shaderstring;
3405         }
3406         else if (!strcmp(filename, "glsl/default.glsl"))
3407         {
3408                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3409                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3410         }
3411         return shaderstring;
3412 }
3413
3414 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3415 {
3416         int i;
3417         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3418         int vertstrings_count = 0;
3419         int geomstrings_count = 0;
3420         int fragstrings_count = 0;
3421         char *vertexstring, *geometrystring, *fragmentstring;
3422         const char *vertstrings_list[32+3];
3423         const char *geomstrings_list[32+3];
3424         const char *fragstrings_list[32+3];
3425         char permutationname[256];
3426
3427         if (p->compiled)
3428                 return;
3429         p->compiled = true;
3430         p->program = 0;
3431
3432         permutationname[0] = 0;
3433         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3434         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3435         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3436
3437         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3438
3439         // the first pretext is which type of shader to compile as
3440         // (later these will all be bound together as a program object)
3441         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3442         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3443         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3444
3445         // the second pretext is the mode (for example a light source)
3446         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3447         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3448         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3449         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3450
3451         // now add all the permutation pretexts
3452         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3453         {
3454                 if (permutation & (1<<i))
3455                 {
3456                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3457                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3458                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3459                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3460                 }
3461                 else
3462                 {
3463                         // keep line numbers correct
3464                         vertstrings_list[vertstrings_count++] = "\n";
3465                         geomstrings_list[geomstrings_count++] = "\n";
3466                         fragstrings_list[fragstrings_count++] = "\n";
3467                 }
3468         }
3469
3470         // now append the shader text itself
3471         vertstrings_list[vertstrings_count++] = vertexstring;
3472         geomstrings_list[geomstrings_count++] = geometrystring;
3473         fragstrings_list[fragstrings_count++] = fragmentstring;
3474
3475         // if any sources were NULL, clear the respective list
3476         if (!vertexstring)
3477                 vertstrings_count = 0;
3478         if (!geometrystring)
3479                 geomstrings_count = 0;
3480         if (!fragmentstring)
3481                 fragstrings_count = 0;
3482
3483         // compile the shader program
3484         if (vertstrings_count + geomstrings_count + fragstrings_count)
3485                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3486         if (p->program)
3487         {
3488                 CHECKGLERROR
3489                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3490                 // look up all the uniform variable names we care about, so we don't
3491                 // have to look them up every time we set them
3492
3493                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3494                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3495                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3496                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3497                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3498                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3499                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3500                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3501                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3502                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3503                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3504                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3505                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3506                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3507                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3508                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3509                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3510                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3511                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3512                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3513                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3514                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3515                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3516                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3517                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3518                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3519                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3520                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3521                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3522                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3523                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3524                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3525                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3526                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3527                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3528                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3529                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3530                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3531                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3532                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3533                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3534                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3535                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3536                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3537                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3538                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3539                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3540                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3541                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3542                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3543                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3544                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3545                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3546                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3547                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3548                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3549                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3550                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3551                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3552                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3553                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3554                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3555                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3556                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3557                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3558                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3559                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3560                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3561                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3562                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3563                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3564                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3565                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3566                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3567                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3568                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3569                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3570                 // initialize the samplers to refer to the texture units we use
3571                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3572                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3573                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3574                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3575                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3576                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3577                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3578                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3579                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3580                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3581                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3582                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3583                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3584                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3585                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3586                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3587                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3588                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3589                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3590                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3591                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3592                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3593                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3594                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3595                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3596                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3597                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3598                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3599                 CHECKGLERROR
3600                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3601         }
3602         else
3603                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3604
3605         // free the strings
3606         if (vertexstring)
3607                 Mem_Free(vertexstring);
3608         if (geometrystring)
3609                 Mem_Free(geometrystring);
3610         if (fragmentstring)
3611                 Mem_Free(fragmentstring);
3612 }
3613
3614 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3615 {
3616         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3617         if (r_glsl_permutation != perm)
3618         {
3619                 r_glsl_permutation = perm;
3620                 if (!r_glsl_permutation->program)
3621                 {
3622                         if (!r_glsl_permutation->compiled)
3623                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3624                         if (!r_glsl_permutation->program)
3625                         {
3626                                 // remove features until we find a valid permutation
3627                                 int i;
3628                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3629                                 {
3630                                         // reduce i more quickly whenever it would not remove any bits
3631                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3632                                         if (!(permutation & j))
3633                                                 continue;
3634                                         permutation -= j;
3635                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3636                                         if (!r_glsl_permutation->compiled)
3637                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3638                                         if (r_glsl_permutation->program)
3639                                                 break;
3640                                 }
3641                                 if (i >= SHADERPERMUTATION_COUNT)
3642                                 {
3643                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3644                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3645                                         qglUseProgramObjectARB(0);CHECKGLERROR
3646                                         return; // no bit left to clear, entire mode is broken
3647                                 }
3648                         }
3649                 }
3650                 CHECKGLERROR
3651                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3652         }
3653         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3654         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3655 }
3656
3657 #ifdef SUPPORTCG
3658 #include <Cg/cgGL.h>
3659 struct r_cg_permutation_s;
3660 typedef struct r_cg_permutation_s
3661 {
3662         /// hash lookup data
3663         struct r_cg_permutation_s *hashnext;
3664         unsigned int mode;
3665         unsigned int permutation;
3666
3667         /// indicates if we have tried compiling this permutation already
3668         qboolean compiled;
3669         /// 0 if compilation failed
3670         CGprogram vprogram;
3671         CGprogram fprogram;
3672         /// locations of detected parameters in programs, or NULL if not found
3673         CGparameter vp_EyePosition;
3674         CGparameter vp_FogPlane;
3675         CGparameter vp_LightDir;
3676         CGparameter vp_LightPosition;
3677         CGparameter vp_ModelToLight;
3678         CGparameter vp_TexMatrix;
3679         CGparameter vp_BackgroundTexMatrix;
3680         CGparameter vp_ModelViewProjectionMatrix;
3681         CGparameter vp_ModelViewMatrix;
3682
3683         CGparameter fp_Texture_First;
3684         CGparameter fp_Texture_Second;
3685         CGparameter fp_Texture_GammaRamps;
3686         CGparameter fp_Texture_Normal;
3687         CGparameter fp_Texture_Color;
3688         CGparameter fp_Texture_Gloss;
3689         CGparameter fp_Texture_Glow;
3690         CGparameter fp_Texture_SecondaryNormal;
3691         CGparameter fp_Texture_SecondaryColor;
3692         CGparameter fp_Texture_SecondaryGloss;
3693         CGparameter fp_Texture_SecondaryGlow;
3694         CGparameter fp_Texture_Pants;
3695         CGparameter fp_Texture_Shirt;
3696         CGparameter fp_Texture_FogMask;
3697         CGparameter fp_Texture_Lightmap;
3698         CGparameter fp_Texture_Deluxemap;
3699         CGparameter fp_Texture_Attenuation;
3700         CGparameter fp_Texture_Cube;
3701         CGparameter fp_Texture_Refraction;
3702         CGparameter fp_Texture_Reflection;
3703         CGparameter fp_Texture_ShadowMapRect;
3704         CGparameter fp_Texture_ShadowMapCube;
3705         CGparameter fp_Texture_ShadowMap2D;
3706         CGparameter fp_Texture_CubeProjection;
3707         CGparameter fp_Texture_ScreenDepth;
3708         CGparameter fp_Texture_ScreenNormalMap;
3709         CGparameter fp_Texture_ScreenDiffuse;
3710         CGparameter fp_Texture_ScreenSpecular;
3711         CGparameter fp_Alpha;
3712         CGparameter fp_BloomBlur_Parameters;
3713         CGparameter fp_ClientTime;
3714         CGparameter fp_Color_Ambient;
3715         CGparameter fp_Color_Diffuse;
3716         CGparameter fp_Color_Specular;
3717         CGparameter fp_Color_Glow;
3718         CGparameter fp_Color_Pants;
3719         CGparameter fp_Color_Shirt;
3720         CGparameter fp_DeferredColor_Ambient;
3721         CGparameter fp_DeferredColor_Diffuse;
3722         CGparameter fp_DeferredColor_Specular;
3723         CGparameter fp_DeferredMod_Diffuse;
3724         CGparameter fp_DeferredMod_Specular;
3725         CGparameter fp_DistortScaleRefractReflect;
3726         CGparameter fp_EyePosition;
3727         CGparameter fp_FogColor;
3728         CGparameter fp_FogHeightFade;
3729         CGparameter fp_FogPlane;
3730         CGparameter fp_FogPlaneViewDist;
3731         CGparameter fp_FogRangeRecip;
3732         CGparameter fp_LightColor;
3733         CGparameter fp_LightDir;
3734         CGparameter fp_LightPosition;
3735         CGparameter fp_OffsetMapping_Scale;
3736         CGparameter fp_PixelSize;
3737         CGparameter fp_ReflectColor;
3738         CGparameter fp_ReflectFactor;
3739         CGparameter fp_ReflectOffset;
3740         CGparameter fp_RefractColor;
3741         CGparameter fp_Saturation;
3742         CGparameter fp_ScreenCenterRefractReflect;
3743         CGparameter fp_ScreenScaleRefractReflect;
3744         CGparameter fp_ScreenToDepth;
3745         CGparameter fp_ShadowMap_Parameters;
3746         CGparameter fp_ShadowMap_TextureScale;
3747         CGparameter fp_SpecularPower;
3748         CGparameter fp_UserVec1;
3749         CGparameter fp_UserVec2;
3750         CGparameter fp_UserVec3;
3751         CGparameter fp_UserVec4;
3752         CGparameter fp_ViewTintColor;
3753         CGparameter fp_ViewToLight;
3754         CGparameter fp_PixelToScreenTexCoord;
3755 }
3756 r_cg_permutation_t;
3757
3758 /// information about each possible shader permutation
3759 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3760 /// currently selected permutation
3761 r_cg_permutation_t *r_cg_permutation;
3762 /// storage for permutations linked in the hash table
3763 memexpandablearray_t r_cg_permutationarray;
3764
3765 #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));}}
3766
3767 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3768 {
3769         //unsigned int hashdepth = 0;
3770         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3771         r_cg_permutation_t *p;
3772         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3773         {
3774                 if (p->mode == mode && p->permutation == permutation)
3775                 {
3776                         //if (hashdepth > 10)
3777                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3778                         return p;
3779                 }
3780                 //hashdepth++;
3781         }
3782         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3783         p->mode = mode;
3784         p->permutation = permutation;
3785         p->hashnext = r_cg_permutationhash[mode][hashindex];
3786         r_cg_permutationhash[mode][hashindex] = p;
3787         //if (hashdepth > 10)
3788         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3789         return p;
3790 }
3791
3792 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3793 {
3794         char *shaderstring;
3795         if (!filename || !filename[0])
3796                 return NULL;
3797         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3798         if (shaderstring)
3799         {
3800                 if (printfromdisknotice)
3801                         Con_DPrintf("from disk %s... ", filename);
3802                 return shaderstring;
3803         }
3804         else if (!strcmp(filename, "cg/default.cg"))
3805         {
3806                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3807                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3808         }
3809         return shaderstring;
3810 }
3811
3812 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3813 {
3814         int i;
3815         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3816         int vertstrings_count = 0, vertstring_length = 0;
3817         int geomstrings_count = 0, geomstring_length = 0;
3818         int fragstrings_count = 0, fragstring_length = 0;
3819         char *t;
3820         char *vertexstring, *geometrystring, *fragmentstring;
3821         char *vertstring, *geomstring, *fragstring;
3822         const char *vertstrings_list[32+3];
3823         const char *geomstrings_list[32+3];
3824         const char *fragstrings_list[32+3];
3825         char permutationname[256];
3826         CGprofile vertexProfile;
3827         CGprofile fragmentProfile;
3828
3829         if (p->compiled)
3830                 return;
3831         p->compiled = true;
3832         p->vprogram = NULL;
3833         p->fprogram = NULL;
3834
3835         permutationname[0] = 0;
3836         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3837         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3838         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3839
3840         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3841
3842         // the first pretext is which type of shader to compile as
3843         // (later these will all be bound together as a program object)
3844         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3845         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3846         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3847
3848         // the second pretext is the mode (for example a light source)
3849         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3850         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3851         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3852         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3853
3854         // now add all the permutation pretexts
3855         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3856         {
3857                 if (permutation & (1<<i))
3858                 {
3859                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3860                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3861                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3862                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3863                 }
3864                 else
3865                 {
3866                         // keep line numbers correct
3867                         vertstrings_list[vertstrings_count++] = "\n";
3868                         geomstrings_list[geomstrings_count++] = "\n";
3869                         fragstrings_list[fragstrings_count++] = "\n";
3870                 }
3871         }
3872
3873         // now append the shader text itself
3874         vertstrings_list[vertstrings_count++] = vertexstring;
3875         geomstrings_list[geomstrings_count++] = geometrystring;
3876         fragstrings_list[fragstrings_count++] = fragmentstring;
3877
3878         // if any sources were NULL, clear the respective list
3879         if (!vertexstring)
3880                 vertstrings_count = 0;
3881         if (!geometrystring)
3882                 geomstrings_count = 0;
3883         if (!fragmentstring)
3884                 fragstrings_count = 0;
3885
3886         vertstring_length = 0;
3887         for (i = 0;i < vertstrings_count;i++)
3888                 vertstring_length += strlen(vertstrings_list[i]);
3889         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3890         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3891                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3892
3893         geomstring_length = 0;
3894         for (i = 0;i < geomstrings_count;i++)
3895                 geomstring_length += strlen(geomstrings_list[i]);
3896         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3897         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3898                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3899
3900         fragstring_length = 0;
3901         for (i = 0;i < fragstrings_count;i++)
3902                 fragstring_length += strlen(fragstrings_list[i]);
3903         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3904         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3905                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3906
3907         CHECKGLERROR
3908         CHECKCGERROR
3909         //vertexProfile = CG_PROFILE_ARBVP1;
3910         //fragmentProfile = CG_PROFILE_ARBFP1;
3911         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3912         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3913         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3914         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3915         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3916         CHECKGLERROR
3917
3918         // compile the vertex program
3919         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL)))
3920         {
3921                 CHECKCGERROR
3922 #if 0
3923                 cgCompileProgram(p->vprogram);CHECKCGERROR
3924                 if (!cgIsProgramCompiled(p->vprogram))
3925                 {
3926                         CHECKCGERROR
3927                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3928                         p->vprogram = 0;
3929                 }
3930                 else
3931 #endif
3932                 {
3933                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3934                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3935                         // look up all the uniform variable names we care about, so we don't
3936                         // have to look them up every time we set them
3937                         CHECKCGERROR
3938                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3939                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3940                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3941                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3942                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3943                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3944                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3945                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3946                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3947                         CHECKCGERROR
3948                 }
3949         }
3950
3951         // compile the fragment program
3952         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL)))
3953         {
3954 #if 0
3955                 cgCompileProgram(p->fprogram);CHECKCGERROR
3956                 if (!cgIsProgramCompiled(p->fprogram))
3957                 {
3958                         CHECKCGERROR
3959                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3960                         p->fprogram = 0;
3961                 }
3962                 else
3963 #endif
3964                 {
3965                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3966                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3967                         CHECKCGERROR
3968                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3969                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3970                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3971                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3972                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3973                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3974                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3975                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3976                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3977                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3978                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3979                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3980                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3981                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3982                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3983                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3984                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3985                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3986                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3987                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3988                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3989                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3990                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3991                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3992                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3993                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3994                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3995                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3996                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
3997                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3998                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
3999                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4000                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4001                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4002                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4003                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4004                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4005                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4006                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4007                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4008                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4009                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4010                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4011                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4012                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4013                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4014                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4015                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4016                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4017                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4018                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4019                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4020                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4021                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4022                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4023                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4024                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4025                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4026                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4027                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4028                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4029                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4030                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4031                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4032                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4033                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4034                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4035                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4036                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4037                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4038                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4039                         p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4040                         CHECKCGERROR
4041                 }
4042         }
4043
4044         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4045                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4046         else
4047                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4048
4049         // free the strings
4050         if (vertstring)
4051                 Mem_Free(vertstring);
4052         if (geomstring)
4053                 Mem_Free(geomstring);
4054         if (fragstring)
4055                 Mem_Free(fragstring);
4056         if (vertexstring)
4057                 Mem_Free(vertexstring);
4058         if (geometrystring)
4059                 Mem_Free(geometrystring);
4060         if (fragmentstring)
4061                 Mem_Free(fragmentstring);
4062 }
4063
4064 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4065 {
4066         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4067         CHECKGLERROR
4068         CHECKCGERROR
4069         if (r_cg_permutation != perm)
4070         {
4071                 r_cg_permutation = perm;
4072                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4073                 {
4074                         if (!r_cg_permutation->compiled)
4075                                 R_CG_CompilePermutation(perm, mode, permutation);
4076                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4077                         {
4078                                 // remove features until we find a valid permutation
4079                                 int i;
4080                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4081                                 {
4082                                         // reduce i more quickly whenever it would not remove any bits
4083                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4084                                         if (!(permutation & j))
4085                                                 continue;
4086                                         permutation -= j;
4087                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4088                                         if (!r_cg_permutation->compiled)
4089                                                 R_CG_CompilePermutation(perm, mode, permutation);
4090                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4091                                                 break;
4092                                 }
4093                                 if (i >= SHADERPERMUTATION_COUNT)
4094                                 {
4095                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4096                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4097                                         return; // no bit left to clear, entire mode is broken
4098                                 }
4099                         }
4100                 }
4101                 CHECKGLERROR
4102                 CHECKCGERROR
4103                 if (r_cg_permutation->vprogram)
4104                 {
4105                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4106                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4107                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4108                 }
4109                 else
4110                 {
4111                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4112                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4113                 }
4114                 if (r_cg_permutation->fprogram)
4115                 {
4116                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4117                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4118                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4119                 }
4120                 else
4121                 {
4122                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4123                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4124                 }
4125         }
4126         CHECKCGERROR
4127         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4128         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4129 }
4130
4131 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4132 {
4133         cgGLSetTextureParameter(param, R_GetTexture(tex));
4134         cgGLEnableTextureParameter(param);
4135 }
4136 #endif
4137
4138 void R_GLSL_Restart_f(void)
4139 {
4140         unsigned int i, limit;
4141         switch(vid.renderpath)
4142         {
4143         case RENDERPATH_GL20:
4144                 {
4145                         r_glsl_permutation_t *p;
4146                         r_glsl_permutation = NULL;
4147                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4148                         for (i = 0;i < limit;i++)
4149                         {
4150                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4151                                 {
4152                                         GL_Backend_FreeProgram(p->program);
4153                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4154                                 }
4155                         }
4156                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4157                 }
4158                 break;
4159         case RENDERPATH_CGGL:
4160 #ifdef SUPPORTCG
4161                 {
4162                         r_cg_permutation_t *p;
4163                         r_cg_permutation = NULL;
4164                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4165                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4166                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4167                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4168                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4169                         for (i = 0;i < limit;i++)
4170                         {
4171                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4172                                 {
4173                                         if (p->vprogram)
4174                                                 cgDestroyProgram(p->vprogram);
4175                                         if (p->fprogram)
4176                                                 cgDestroyProgram(p->fprogram);
4177                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4178                                 }
4179                         }
4180                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4181                 }
4182                 break;
4183 #endif
4184         case RENDERPATH_GL13:
4185         case RENDERPATH_GL11:
4186                 break;
4187         }
4188 }
4189
4190 void R_GLSL_DumpShader_f(void)
4191 {
4192         int i;
4193         qfile_t *file;
4194
4195         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4196         if (file)
4197         {
4198                 FS_Print(file, "/* The engine may define the following macros:\n");
4199                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4200                 for (i = 0;i < SHADERMODE_COUNT;i++)
4201                         FS_Print(file, glslshadermodeinfo[i].pretext);
4202                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4203                         FS_Print(file, shaderpermutationinfo[i].pretext);
4204                 FS_Print(file, "*/\n");
4205                 FS_Print(file, builtinshaderstring);
4206                 FS_Close(file);
4207                 Con_Printf("glsl/default.glsl written\n");
4208         }
4209         else
4210                 Con_Printf("failed to write to glsl/default.glsl\n");
4211
4212 #ifdef SUPPORTCG
4213         file = FS_OpenRealFile("cg/default.cg", "w", false);
4214         if (file)
4215         {
4216                 FS_Print(file, "/* The engine may define the following macros:\n");
4217                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4218                 for (i = 0;i < SHADERMODE_COUNT;i++)
4219                         FS_Print(file, cgshadermodeinfo[i].pretext);
4220                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4221                         FS_Print(file, shaderpermutationinfo[i].pretext);
4222                 FS_Print(file, "*/\n");
4223                 FS_Print(file, builtincgshaderstring);
4224                 FS_Close(file);
4225                 Con_Printf("cg/default.cg written\n");
4226         }
4227         else
4228                 Con_Printf("failed to write to cg/default.cg\n");
4229 #endif
4230 }
4231
4232 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4233 {
4234         if (!second)
4235                 texturemode = GL_MODULATE;
4236         switch (vid.renderpath)
4237         {
4238         case RENDERPATH_GL20:
4239                 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))));
4240                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4241                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4242                 break;
4243         case RENDERPATH_CGGL:
4244 #ifdef SUPPORTCG
4245                 CHECKCGERROR
4246                 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))));
4247                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4248                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4249 #endif
4250                 break;
4251         case RENDERPATH_GL13:
4252                 R_Mesh_TexBind(0, first );
4253                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4254                 R_Mesh_TexBind(1, second);
4255                 if (second)
4256                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4257                 break;
4258         case RENDERPATH_GL11:
4259                 R_Mesh_TexBind(0, first );
4260                 break;
4261         }
4262 }
4263
4264 void R_SetupShader_DepthOrShadow(void)
4265 {
4266         switch (vid.renderpath)
4267         {
4268         case RENDERPATH_GL20:
4269                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4270                 break;
4271         case RENDERPATH_CGGL:
4272 #ifdef SUPPORTCG
4273                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4274 #endif
4275                 break;
4276         case RENDERPATH_GL13:
4277                 R_Mesh_TexBind(0, 0);
4278                 R_Mesh_TexBind(1, 0);
4279                 break;
4280         case RENDERPATH_GL11:
4281                 R_Mesh_TexBind(0, 0);
4282                 break;
4283         }
4284 }
4285
4286 void R_SetupShader_ShowDepth(void)
4287 {
4288         switch (vid.renderpath)
4289         {
4290         case RENDERPATH_GL20:
4291                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4292                 break;
4293         case RENDERPATH_CGGL:
4294 #ifdef SUPPORTCG
4295                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4296 #endif
4297                 break;
4298         case RENDERPATH_GL13:
4299                 break;
4300         case RENDERPATH_GL11:
4301                 break;
4302         }
4303 }
4304
4305 extern qboolean r_shadow_usingdeferredprepass;
4306 extern cvar_t r_shadow_deferred_8bitrange;
4307 extern rtexture_t *r_shadow_attenuationgradienttexture;
4308 extern rtexture_t *r_shadow_attenuation2dtexture;
4309 extern rtexture_t *r_shadow_attenuation3dtexture;
4310 extern qboolean r_shadow_usingshadowmaprect;
4311 extern qboolean r_shadow_usingshadowmapcube;
4312 extern qboolean r_shadow_usingshadowmap2d;
4313 extern float r_shadow_shadowmap_texturescale[2];
4314 extern float r_shadow_shadowmap_parameters[4];
4315 extern qboolean r_shadow_shadowmapvsdct;
4316 extern qboolean r_shadow_shadowmapsampler;
4317 extern int r_shadow_shadowmappcf;
4318 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4319 extern rtexture_t *r_shadow_shadowmap2dtexture;
4320 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4321 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4322 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4323 extern int r_shadow_prepass_width;
4324 extern int r_shadow_prepass_height;
4325 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4326 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4327 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4328 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4329 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4330 {
4331         // select a permutation of the lighting shader appropriate to this
4332         // combination of texture, entity, light source, and fogging, only use the
4333         // minimum features necessary to avoid wasting rendering time in the
4334         // fragment shader on features that are not being used
4335         unsigned int permutation = 0;
4336         unsigned int mode = 0;
4337         float m16f[16];
4338         if (rsurfacepass == RSURFPASS_BACKGROUND)
4339         {
4340                 // distorted background
4341                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4342                         mode = SHADERMODE_WATER;
4343                 else
4344                         mode = SHADERMODE_REFRACTION;
4345                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4346                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4347                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4348                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4349                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4350                 R_Mesh_ColorPointer(NULL, 0, 0);
4351                 GL_AlphaTest(false);
4352                 GL_BlendFunc(GL_ONE, GL_ZERO);
4353         }
4354         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4355         {
4356                 if (r_glsl_offsetmapping.integer)
4357                 {
4358                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4359                         if (r_glsl_offsetmapping_reliefmapping.integer)
4360                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4361                 }
4362                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4363                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4364                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4365                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4366                 // normalmap (deferred prepass), may use alpha test on diffuse
4367                 mode = SHADERMODE_DEFERREDGEOMETRY;
4368                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4369                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4370                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4371                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4372                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4373                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4374                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4375                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4376                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4377                 else
4378                         R_Mesh_ColorPointer(NULL, 0, 0);
4379                 GL_AlphaTest(false);
4380                 GL_BlendFunc(GL_ONE, GL_ZERO);
4381         }
4382         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4383         {
4384                 if (r_glsl_offsetmapping.integer)
4385                 {
4386                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4387                         if (r_glsl_offsetmapping_reliefmapping.integer)
4388                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4389                 }
4390                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4391                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4392                 // light source
4393                 mode = SHADERMODE_LIGHTSOURCE;
4394                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4395                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4396                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4397                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4398                 if (diffusescale > 0)
4399                         permutation |= SHADERPERMUTATION_DIFFUSE;
4400                 if (specularscale > 0)
4401                 {
4402                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4403                         if (r_shadow_glossexact.integer)
4404                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4405                 }
4406                 if (r_refdef.fogenabled)
4407                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4408                 if (rsurface.texture->colormapping)
4409                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4410                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4411                 {
4412                         if (r_shadow_usingshadowmaprect)
4413                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4414                         if (r_shadow_usingshadowmap2d)
4415                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4416                         if (r_shadow_usingshadowmapcube)
4417                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4418                         else if(r_shadow_shadowmapvsdct)
4419                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4420
4421                         if (r_shadow_shadowmapsampler)
4422                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4423                         if (r_shadow_shadowmappcf > 1)
4424                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4425                         else if (r_shadow_shadowmappcf)
4426                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4427                 }
4428                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4429                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4430                 {
4431                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4432                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4433                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4434                 }
4435                 else
4436                 {
4437                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4438                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4439                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4440                 }
4441                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4442                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4443                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4444                 else
4445                         R_Mesh_ColorPointer(NULL, 0, 0);
4446                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4447                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4448         }
4449         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4450         {
4451                 if (r_glsl_offsetmapping.integer)
4452                 {
4453                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4454                         if (r_glsl_offsetmapping_reliefmapping.integer)
4455                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4456                 }
4457                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4458                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4459                 // unshaded geometry (fullbright or ambient model lighting)
4460                 mode = SHADERMODE_FLATCOLOR;
4461                 ambientscale = diffusescale = specularscale = 0;
4462                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4463                         permutation |= SHADERPERMUTATION_GLOW;
4464                 if (r_refdef.fogenabled)
4465                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4466                 if (rsurface.texture->colormapping)
4467                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4468                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4469                         permutation |= SHADERPERMUTATION_REFLECTION;
4470                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4471                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4472                 {
4473                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4474                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4475                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4476                 }
4477                 else
4478                 {
4479                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4480                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4481                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4482                 }
4483                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4484                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4485                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4486                 else
4487                         R_Mesh_ColorPointer(NULL, 0, 0);
4488                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4489                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4490         }
4491         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4492         {
4493                 if (r_glsl_offsetmapping.integer)
4494                 {
4495                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4496                         if (r_glsl_offsetmapping_reliefmapping.integer)
4497                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4498                 }
4499                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4500                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4501                 // directional model lighting
4502                 mode = SHADERMODE_LIGHTDIRECTION;
4503                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4504                         permutation |= SHADERPERMUTATION_GLOW;
4505                 permutation |= SHADERPERMUTATION_DIFFUSE;
4506                 if (specularscale > 0)
4507                 {
4508                         permutation |= SHADERPERMUTATION_SPECULAR;
4509                         if (r_shadow_glossexact.integer)
4510                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4511                 }
4512                 if (r_refdef.fogenabled)
4513                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4514                 if (rsurface.texture->colormapping)
4515                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4516                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4517                         permutation |= SHADERPERMUTATION_REFLECTION;
4518                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4519                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4520                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4521                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4522                 {
4523                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4524                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4525                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4526                 }
4527                 else
4528                 {
4529                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4530                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4531                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4532                 }
4533                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4534                 R_Mesh_ColorPointer(NULL, 0, 0);
4535                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4536                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4537         }
4538         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4539         {
4540                 if (r_glsl_offsetmapping.integer)
4541                 {
4542                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4543                         if (r_glsl_offsetmapping_reliefmapping.integer)
4544                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4545                 }
4546                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4547                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4548                 // ambient model lighting
4549                 mode = SHADERMODE_LIGHTDIRECTION;
4550                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4551                         permutation |= SHADERPERMUTATION_GLOW;
4552                 if (r_refdef.fogenabled)
4553                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4554                 if (rsurface.texture->colormapping)
4555                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4556                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4557                         permutation |= SHADERPERMUTATION_REFLECTION;
4558                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4559                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4560                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4561                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4562                 {
4563                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4564                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4565                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4566                 }
4567                 else
4568                 {
4569                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4570                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4571                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4572                 }
4573                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4574                 R_Mesh_ColorPointer(NULL, 0, 0);
4575                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4576                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4577         }
4578         else
4579         {
4580                 if (r_glsl_offsetmapping.integer)
4581                 {
4582                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4583                         if (r_glsl_offsetmapping_reliefmapping.integer)
4584                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4585                 }
4586                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4587                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4588                 // lightmapped wall
4589                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4590                         permutation |= SHADERPERMUTATION_GLOW;
4591                 if (r_refdef.fogenabled)
4592                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4593                 if (rsurface.texture->colormapping)
4594                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4595                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4596                         permutation |= SHADERPERMUTATION_REFLECTION;
4597                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4598                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4599                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4600                 {
4601                         // deluxemapping (light direction texture)
4602                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4603                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4604                         else
4605                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4606                         permutation |= SHADERPERMUTATION_DIFFUSE;
4607                         if (specularscale > 0)
4608                         {
4609                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4610                                 if (r_shadow_glossexact.integer)
4611                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4612                         }
4613                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4614                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4615                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4616                         else
4617                                 R_Mesh_ColorPointer(NULL, 0, 0);
4618                 }
4619                 else if (r_glsl_deluxemapping.integer >= 2)
4620                 {
4621                         // fake deluxemapping (uniform light direction in tangentspace)
4622                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4623                         permutation |= SHADERPERMUTATION_DIFFUSE;
4624                         if (specularscale > 0)
4625                         {
4626                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4627                                 if (r_shadow_glossexact.integer)
4628                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4629                         }
4630                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4631                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4632                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4633                         else
4634                                 R_Mesh_ColorPointer(NULL, 0, 0);
4635                 }
4636                 else if (rsurface.uselightmaptexture)
4637                 {
4638                         // ordinary lightmapping (q1bsp, q3bsp)
4639                         mode = SHADERMODE_LIGHTMAP;
4640                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4641                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4642                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4643                         else
4644                                 R_Mesh_ColorPointer(NULL, 0, 0);
4645                 }
4646                 else
4647                 {
4648                         // ordinary vertex coloring (q3bsp)
4649                         mode = SHADERMODE_VERTEXCOLOR;
4650                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4651                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4652                 }
4653                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4654                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4655                 {
4656                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4657                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4658                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4659                 }
4660                 else
4661                 {
4662                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4663                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4664                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4665                 }
4666                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4667                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4668         }
4669         switch(vid.renderpath)
4670         {
4671         case RENDERPATH_GL20:
4672                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4673                 if (mode == SHADERMODE_LIGHTSOURCE)
4674                 {
4675                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4676                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4677                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4678                         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);
4679                         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);
4680                         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);
4681         
4682                         // additive passes are only darkened by fog, not tinted
4683                         if (r_glsl_permutation->loc_FogColor >= 0)
4684                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4685                         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]);
4686                         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]);
4687                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4688                 }
4689                 else
4690                 {
4691                         if (mode == SHADERMODE_FLATCOLOR)
4692                         {
4693                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4694                         }
4695                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4696                         {
4697                                 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]);
4698                                 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]);
4699                                 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);
4700                                 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);
4701                                 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);
4702                                 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]);
4703                                 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]);
4704                         }
4705                         else
4706                         {
4707                                 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]);
4708                                 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]);
4709                                 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);
4710                                 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);
4711                                 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);
4712                         }
4713                         // additive passes are only darkened by fog, not tinted
4714                         if (r_glsl_permutation->loc_FogColor >= 0)
4715                         {
4716                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4717                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4718                                 else
4719                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4720                         }
4721                         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);
4722                         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]);
4723                         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]);
4724                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4725                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4726                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4727                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4728                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4729                 }
4730                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4731                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4732                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4733                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4734                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4735                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4736                 {
4737                         if (rsurface.texture->pantstexture)
4738                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4739                         else
4740                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4741                 }
4742                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4743                 {
4744                         if (rsurface.texture->shirttexture)
4745                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4746                         else
4747                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4748                 }
4749                 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]);
4750                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4751                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4752                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4753                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4754                 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]);
4755                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4756
4757         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4758         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4759         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4760                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4761                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4762                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4763                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4764                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4765                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4766                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4767                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4768                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4769                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4770                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4771                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4772                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4773                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4774                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4775                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4776                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4777                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4778                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4779                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4780                 if (rsurface.rtlight)
4781                 {
4782                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4783                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4784                         if (r_shadow_usingshadowmapcube)
4785                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4786                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4787                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4788                 }
4789                 CHECKGLERROR
4790                 break;
4791         case RENDERPATH_CGGL:
4792 #ifdef SUPPORTCG
4793                 R_SetupShader_SetPermutationCG(mode, permutation);
4794                 if (mode == SHADERMODE_LIGHTSOURCE)
4795                 {
4796                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4797                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4798                 }
4799                 else
4800                 {
4801                         if (mode == SHADERMODE_LIGHTDIRECTION)
4802                         {
4803                                 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
4804                         }
4805                 }
4806                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4807                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4808                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4809                 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
4810                 CHECKGLERROR
4811
4812                 if (mode == SHADERMODE_LIGHTSOURCE)
4813                 {
4814                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4815                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4816                         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
4817                         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
4818                         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
4819
4820                         // additive passes are only darkened by fog, not tinted
4821                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4822                         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
4823                         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
4824                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4825                 }
4826                 else
4827                 {
4828                         if (mode == SHADERMODE_FLATCOLOR)
4829                         {
4830                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4831                         }
4832                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4833                         {
4834                                 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
4835                                 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
4836                                 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
4837                                 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
4838                                 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
4839                                 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
4840                                 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
4841                         }
4842                         else
4843                         {
4844                                 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
4845                                 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
4846                                 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
4847                                 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
4848                                 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
4849                         }
4850                         // additive passes are only darkened by fog, not tinted
4851                         if (r_cg_permutation->fp_FogColor)
4852                         {
4853                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4854                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4855                                 else
4856                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4857                                 CHECKCGERROR
4858                         }
4859                         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
4860                         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
4861                         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
4862                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4863                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4864                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4865                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4866                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4867                 }
4868                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4869                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4870                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4871                 if (r_cg_permutation->fp_Color_Pants)
4872                 {
4873                         if (rsurface.texture->pantstexture)
4874                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4875                         else
4876                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4877                         CHECKCGERROR
4878                 }
4879                 if (r_cg_permutation->fp_Color_Shirt)
4880                 {
4881                         if (rsurface.texture->shirttexture)
4882                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4883                         else
4884                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4885                         CHECKCGERROR
4886                 }
4887                 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
4888                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4889                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4890                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4891                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4892                 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
4893                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
4894
4895         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
4896         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
4897         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
4898                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
4899                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
4900                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
4901                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
4902                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
4903                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
4904                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
4905                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
4906                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
4907                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
4908                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
4909                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
4910                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
4911                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4912                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
4913                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
4914                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4915                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4916                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
4917                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
4918                 if (rsurface.rtlight)
4919                 {
4920                         if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4921                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4922                         if (r_shadow_usingshadowmapcube)
4923                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4924                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4925                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4926                 }
4927
4928                 CHECKGLERROR
4929 #endif
4930                 break;
4931         case RENDERPATH_GL13:
4932         case RENDERPATH_GL11:
4933                 break;
4934         }
4935 }
4936
4937 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4938 {
4939         // select a permutation of the lighting shader appropriate to this
4940         // combination of texture, entity, light source, and fogging, only use the
4941         // minimum features necessary to avoid wasting rendering time in the
4942         // fragment shader on features that are not being used
4943         unsigned int permutation = 0;
4944         unsigned int mode = 0;
4945         const float *lightcolorbase = rtlight->currentcolor;
4946         float ambientscale = rtlight->ambientscale;
4947         float diffusescale = rtlight->diffusescale;
4948         float specularscale = rtlight->specularscale;
4949         // this is the location of the light in view space
4950         vec3_t viewlightorigin;
4951         // this transforms from view space (camera) to light space (cubemap)
4952         matrix4x4_t viewtolight;
4953         matrix4x4_t lighttoview;
4954         float viewtolight16f[16];
4955         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4956         // light source
4957         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4958         if (rtlight->currentcubemap != r_texture_whitecube)
4959                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4960         if (diffusescale > 0)
4961                 permutation |= SHADERPERMUTATION_DIFFUSE;
4962         if (specularscale > 0)
4963         {
4964                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4965                 if (r_shadow_glossexact.integer)
4966                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4967         }
4968         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4969         {
4970                 if (r_shadow_usingshadowmaprect)
4971                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4972                 if (r_shadow_usingshadowmap2d)
4973                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4974                 if (r_shadow_usingshadowmapcube)
4975                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4976                 else if(r_shadow_shadowmapvsdct)
4977                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4978
4979                 if (r_shadow_shadowmapsampler)
4980                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4981                 if (r_shadow_shadowmappcf > 1)
4982                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4983                 else if (r_shadow_shadowmappcf)
4984                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4985         }
4986         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4987         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4988         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4989         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4990         switch(vid.renderpath)
4991         {
4992         case RENDERPATH_GL20:
4993                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4994                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4995                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4996                 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);
4997                 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);
4998                 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);
4999                 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]);
5000                 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]);
5001                 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));
5002                 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]);
5003                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5004
5005                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5006                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5007                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5008                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5009                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5010                 if (r_shadow_usingshadowmapcube)
5011                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5012                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5013                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5014                 break;
5015         case RENDERPATH_CGGL:
5016 #ifdef SUPPORTCG
5017                 R_SetupShader_SetPermutationCG(mode, permutation);
5018                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5019                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5020                 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
5021                 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
5022                 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
5023                 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
5024                 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
5025                 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
5026                 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
5027                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5028
5029                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5030                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5031                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5032                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5033                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5034                 if (r_shadow_usingshadowmapcube)
5035                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5036                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5037                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5038 #endif
5039                 break;
5040         case RENDERPATH_GL13:
5041         case RENDERPATH_GL11:
5042                 break;
5043         }
5044 }
5045
5046 #define SKINFRAME_HASH 1024
5047
5048 typedef struct
5049 {
5050         int loadsequence; // incremented each level change
5051         memexpandablearray_t array;
5052         skinframe_t *hash[SKINFRAME_HASH];
5053 }
5054 r_skinframe_t;
5055 r_skinframe_t r_skinframe;
5056
5057 void R_SkinFrame_PrepareForPurge(void)
5058 {
5059         r_skinframe.loadsequence++;
5060         // wrap it without hitting zero
5061         if (r_skinframe.loadsequence >= 200)
5062                 r_skinframe.loadsequence = 1;
5063 }
5064
5065 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5066 {
5067         if (!skinframe)
5068                 return;
5069         // mark the skinframe as used for the purging code
5070         skinframe->loadsequence = r_skinframe.loadsequence;
5071 }
5072
5073 void R_SkinFrame_Purge(void)
5074 {
5075         int i;
5076         skinframe_t *s;
5077         for (i = 0;i < SKINFRAME_HASH;i++)
5078         {
5079                 for (s = r_skinframe.hash[i];s;s = s->next)
5080                 {
5081                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5082                         {
5083                                 if (s->merged == s->base)
5084                                         s->merged = NULL;
5085                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5086                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5087                                 R_PurgeTexture(s->merged);s->merged = NULL;
5088                                 R_PurgeTexture(s->base  );s->base   = NULL;
5089                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5090                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5091                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5092                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5093                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5094                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5095                                 s->loadsequence = 0;
5096                         }
5097                 }
5098         }
5099 }
5100
5101 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5102         skinframe_t *item;
5103         char basename[MAX_QPATH];
5104
5105         Image_StripImageExtension(name, basename, sizeof(basename));
5106
5107         if( last == NULL ) {
5108                 int hashindex;
5109                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5110                 item = r_skinframe.hash[hashindex];
5111         } else {
5112                 item = last->next;
5113         }
5114
5115         // linearly search through the hash bucket
5116         for( ; item ; item = item->next ) {
5117                 if( !strcmp( item->basename, basename ) ) {
5118                         return item;
5119                 }
5120         }
5121         return NULL;
5122 }
5123
5124 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5125 {
5126         skinframe_t *item;
5127         int hashindex;
5128         char basename[MAX_QPATH];
5129
5130         Image_StripImageExtension(name, basename, sizeof(basename));
5131
5132         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5133         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5134                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5135                         break;
5136
5137         if (!item) {
5138                 rtexture_t *dyntexture;
5139                 // check whether its a dynamic texture
5140                 dyntexture = CL_GetDynTexture( basename );
5141                 if (!add && !dyntexture)
5142                         return NULL;
5143                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5144                 memset(item, 0, sizeof(*item));
5145                 strlcpy(item->basename, basename, sizeof(item->basename));
5146                 item->base = dyntexture; // either NULL or dyntexture handle
5147                 item->textureflags = textureflags;
5148                 item->comparewidth = comparewidth;
5149                 item->compareheight = compareheight;
5150                 item->comparecrc = comparecrc;
5151                 item->next = r_skinframe.hash[hashindex];
5152                 r_skinframe.hash[hashindex] = item;
5153         }
5154         else if( item->base == NULL )
5155         {
5156                 rtexture_t *dyntexture;
5157                 // check whether its a dynamic texture
5158                 // 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]
5159                 dyntexture = CL_GetDynTexture( basename );
5160                 item->base = dyntexture; // either NULL or dyntexture handle
5161         }
5162
5163         R_SkinFrame_MarkUsed(item);
5164         return item;
5165 }
5166
5167 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5168         { \
5169                 unsigned long long avgcolor[5], wsum; \
5170                 int pix, comp, w; \
5171                 avgcolor[0] = 0; \
5172                 avgcolor[1] = 0; \
5173                 avgcolor[2] = 0; \
5174                 avgcolor[3] = 0; \
5175                 avgcolor[4] = 0; \
5176                 wsum = 0; \
5177                 for(pix = 0; pix < cnt; ++pix) \
5178                 { \
5179                         w = 0; \
5180                         for(comp = 0; comp < 3; ++comp) \
5181                                 w += getpixel; \
5182                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5183                         { \
5184                                 ++wsum; \
5185                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5186                                 w = getpixel; \
5187                                 for(comp = 0; comp < 3; ++comp) \
5188                                         avgcolor[comp] += getpixel * w; \
5189                                 avgcolor[3] += w; \
5190                         } \
5191                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5192                         avgcolor[4] += getpixel; \
5193                 } \
5194                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5195                         avgcolor[3] = 1; \
5196                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5197                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5198                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5199                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5200         }
5201
5202 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5203 {
5204         int j;
5205         unsigned char *pixels;
5206         unsigned char *bumppixels;
5207         unsigned char *basepixels = NULL;
5208         int basepixels_width = 0;
5209         int basepixels_height = 0;
5210         skinframe_t *skinframe;
5211         rtexture_t *ddsbase = NULL;
5212         qboolean ddshasalpha = false;
5213         float ddsavgcolor[4];
5214         char basename[MAX_QPATH];
5215
5216         if (cls.state == ca_dedicated)
5217                 return NULL;
5218
5219         // return an existing skinframe if already loaded
5220         // if loading of the first image fails, don't make a new skinframe as it
5221         // would cause all future lookups of this to be missing
5222         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5223         if (skinframe && skinframe->base)
5224                 return skinframe;
5225
5226         Image_StripImageExtension(name, basename, sizeof(basename));
5227
5228         // check for DDS texture file first
5229         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5230         {
5231                 basepixels = loadimagepixelsbgra(name, complain, true);
5232                 if (basepixels == NULL)
5233                         return NULL;
5234         }
5235
5236         if (developer_loading.integer)
5237                 Con_Printf("loading skin \"%s\"\n", name);
5238
5239         // we've got some pixels to store, so really allocate this new texture now
5240         if (!skinframe)
5241                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5242         skinframe->stain = NULL;
5243         skinframe->merged = NULL;
5244         skinframe->base = NULL;
5245         skinframe->pants = NULL;
5246         skinframe->shirt = NULL;
5247         skinframe->nmap = NULL;
5248         skinframe->gloss = NULL;
5249         skinframe->glow = NULL;
5250         skinframe->fog = NULL;
5251         skinframe->hasalpha = false;
5252
5253         if (ddsbase)
5254         {
5255                 skinframe->base = ddsbase;
5256                 skinframe->hasalpha = ddshasalpha;
5257                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5258                 if (r_loadfog && skinframe->hasalpha)
5259                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5260                 //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]);
5261         }
5262         else
5263         {
5264                 basepixels_width = image_width;
5265                 basepixels_height = image_height;
5266                 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);
5267                 if (textureflags & TEXF_ALPHA)
5268                 {
5269                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5270                         {
5271                                 if (basepixels[j] < 255)
5272                                 {
5273                                         skinframe->hasalpha = true;
5274                                         break;
5275                                 }
5276                         }
5277                         if (r_loadfog && skinframe->hasalpha)
5278                         {
5279                                 // has transparent pixels
5280                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5281                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5282                                 {
5283                                         pixels[j+0] = 255;
5284                                         pixels[j+1] = 255;
5285                                         pixels[j+2] = 255;
5286                                         pixels[j+3] = basepixels[j+3];
5287                                 }
5288                                 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);
5289                                 Mem_Free(pixels);
5290                         }
5291                 }
5292                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5293                 //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]);
5294                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5295                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5296                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5297                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5298         }
5299
5300         if (r_loaddds)
5301         {
5302                 if (r_loadnormalmap)
5303                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5304                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5305                 if (r_loadgloss)
5306                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5307                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5308                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5309         }
5310
5311         // _norm is the name used by tenebrae and has been adopted as standard
5312         if (r_loadnormalmap && skinframe->nmap == NULL)
5313         {
5314                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5315                 {
5316                         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);
5317                         Mem_Free(pixels);
5318                         pixels = NULL;
5319                 }
5320                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5321                 {
5322                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5323                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5324                         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);
5325                         Mem_Free(pixels);
5326                         Mem_Free(bumppixels);
5327                 }
5328                 else if (r_shadow_bumpscale_basetexture.value > 0)
5329                 {
5330                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5331                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5332                         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);
5333                         Mem_Free(pixels);
5334                 }
5335                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5336                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5337         }
5338
5339         // _luma is supported only for tenebrae compatibility
5340         // _glow is the preferred name
5341         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5342         {
5343                 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);
5344                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5345                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5346                 Mem_Free(pixels);pixels = NULL;
5347         }
5348
5349         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5350         {
5351                 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);
5352                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5353                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5354                 Mem_Free(pixels);
5355                 pixels = NULL;
5356         }
5357
5358         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5359         {
5360                 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);
5361                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5362                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5363                 Mem_Free(pixels);
5364                 pixels = NULL;
5365         }
5366
5367         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5368         {
5369                 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);
5370                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5371                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5372                 Mem_Free(pixels);
5373                 pixels = NULL;
5374         }
5375
5376         if (basepixels)
5377                 Mem_Free(basepixels);
5378
5379         return skinframe;
5380 }
5381
5382 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5383 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5384 {
5385         int i;
5386         unsigned char *temp1, *temp2;
5387         skinframe_t *skinframe;
5388
5389         if (cls.state == ca_dedicated)
5390                 return NULL;
5391
5392         // if already loaded just return it, otherwise make a new skinframe
5393         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5394         if (skinframe && skinframe->base)
5395                 return skinframe;
5396
5397         skinframe->stain = NULL;
5398         skinframe->merged = NULL;
5399         skinframe->base = NULL;
5400         skinframe->pants = NULL;
5401         skinframe->shirt = NULL;
5402         skinframe->nmap = NULL;
5403         skinframe->gloss = NULL;
5404         skinframe->glow = NULL;
5405         skinframe->fog = NULL;
5406         skinframe->hasalpha = false;
5407
5408         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5409         if (!skindata)
5410                 return NULL;
5411
5412         if (developer_loading.integer)
5413                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5414
5415         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5416         {
5417                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5418                 temp2 = temp1 + width * height * 4;
5419                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5420                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5421                 Mem_Free(temp1);
5422         }
5423         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5424         if (textureflags & TEXF_ALPHA)
5425         {
5426                 for (i = 3;i < width * height * 4;i += 4)
5427                 {
5428                         if (skindata[i] < 255)
5429                         {
5430                                 skinframe->hasalpha = true;
5431                                 break;
5432                         }
5433                 }
5434                 if (r_loadfog && skinframe->hasalpha)
5435                 {
5436                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5437                         memcpy(fogpixels, skindata, width * height * 4);
5438                         for (i = 0;i < width * height * 4;i += 4)
5439                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5440                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5441                         Mem_Free(fogpixels);
5442                 }
5443         }
5444
5445         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5446         //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]);
5447
5448         return skinframe;
5449 }
5450
5451 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5452 {
5453         int i;
5454         int featuresmask;
5455         skinframe_t *skinframe;
5456
5457         if (cls.state == ca_dedicated)
5458                 return NULL;
5459
5460         // if already loaded just return it, otherwise make a new skinframe
5461         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5462         if (skinframe && skinframe->base)
5463                 return skinframe;
5464
5465         skinframe->stain = NULL;
5466         skinframe->merged = NULL;
5467         skinframe->base = NULL;
5468         skinframe->pants = NULL;
5469         skinframe->shirt = NULL;
5470         skinframe->nmap = NULL;
5471         skinframe->gloss = NULL;
5472         skinframe->glow = NULL;
5473         skinframe->fog = NULL;
5474         skinframe->hasalpha = false;
5475
5476         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5477         if (!skindata)
5478                 return NULL;
5479
5480         if (developer_loading.integer)
5481                 Con_Printf("loading quake skin \"%s\"\n", name);
5482
5483         // 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)
5484         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5485         memcpy(skinframe->qpixels, skindata, width*height);
5486         skinframe->qwidth = width;
5487         skinframe->qheight = height;
5488
5489         featuresmask = 0;
5490         for (i = 0;i < width * height;i++)
5491                 featuresmask |= palette_featureflags[skindata[i]];
5492
5493         skinframe->hasalpha = false;
5494         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5495         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5496         skinframe->qgeneratemerged = true;
5497         skinframe->qgeneratebase = skinframe->qhascolormapping;
5498         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5499
5500         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5501         //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]);
5502
5503         return skinframe;
5504 }
5505
5506 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5507 {
5508         int width;
5509         int height;
5510         unsigned char *skindata;
5511
5512         if (!skinframe->qpixels)
5513                 return;
5514
5515         if (!skinframe->qhascolormapping)
5516                 colormapped = false;
5517
5518         if (colormapped)
5519         {
5520                 if (!skinframe->qgeneratebase)
5521                         return;
5522         }
5523         else
5524         {
5525                 if (!skinframe->qgeneratemerged)
5526                         return;
5527         }
5528
5529         width = skinframe->qwidth;
5530         height = skinframe->qheight;
5531         skindata = skinframe->qpixels;
5532
5533         if (skinframe->qgeneratenmap)
5534         {
5535                 unsigned char *temp1, *temp2;
5536                 skinframe->qgeneratenmap = false;
5537                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5538                 temp2 = temp1 + width * height * 4;
5539                 // use either a custom palette or the quake palette
5540                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5541                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5542                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5543                 Mem_Free(temp1);
5544         }
5545
5546         if (skinframe->qgenerateglow)
5547         {
5548                 skinframe->qgenerateglow = false;
5549                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5550         }
5551
5552         if (colormapped)
5553         {
5554                 skinframe->qgeneratebase = false;
5555                 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);
5556                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5557                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5558         }
5559         else
5560         {
5561                 skinframe->qgeneratemerged = false;
5562                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5563         }
5564
5565         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5566         {
5567                 Mem_Free(skinframe->qpixels);
5568                 skinframe->qpixels = NULL;
5569         }
5570 }
5571
5572 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)
5573 {
5574         int i;
5575         skinframe_t *skinframe;
5576
5577         if (cls.state == ca_dedicated)
5578                 return NULL;
5579
5580         // if already loaded just return it, otherwise make a new skinframe
5581         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5582         if (skinframe && skinframe->base)
5583                 return skinframe;
5584
5585         skinframe->stain = NULL;
5586         skinframe->merged = NULL;
5587         skinframe->base = NULL;
5588         skinframe->pants = NULL;
5589         skinframe->shirt = NULL;
5590         skinframe->nmap = NULL;
5591         skinframe->gloss = NULL;
5592         skinframe->glow = NULL;
5593         skinframe->fog = NULL;
5594         skinframe->hasalpha = false;
5595
5596         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5597         if (!skindata)
5598                 return NULL;
5599
5600         if (developer_loading.integer)
5601                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5602
5603         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5604         if (textureflags & TEXF_ALPHA)
5605         {
5606                 for (i = 0;i < width * height;i++)
5607                 {
5608                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5609                         {
5610                                 skinframe->hasalpha = true;
5611                                 break;
5612                         }
5613                 }
5614                 if (r_loadfog && skinframe->hasalpha)
5615                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5616         }
5617
5618         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5619         //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]);
5620
5621         return skinframe;
5622 }
5623
5624 skinframe_t *R_SkinFrame_LoadMissing(void)
5625 {
5626         skinframe_t *skinframe;
5627
5628         if (cls.state == ca_dedicated)
5629                 return NULL;
5630
5631         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5632         skinframe->stain = NULL;
5633         skinframe->merged = NULL;
5634         skinframe->base = NULL;
5635         skinframe->pants = NULL;
5636         skinframe->shirt = NULL;
5637         skinframe->nmap = NULL;
5638         skinframe->gloss = NULL;
5639         skinframe->glow = NULL;
5640         skinframe->fog = NULL;
5641         skinframe->hasalpha = false;
5642
5643         skinframe->avgcolor[0] = rand() / RAND_MAX;
5644         skinframe->avgcolor[1] = rand() / RAND_MAX;
5645         skinframe->avgcolor[2] = rand() / RAND_MAX;
5646         skinframe->avgcolor[3] = 1;
5647
5648         return skinframe;
5649 }
5650
5651 void R_Main_FreeViewCache(void)
5652 {
5653         if (r_refdef.viewcache.entityvisible)
5654                 Mem_Free(r_refdef.viewcache.entityvisible);
5655         if (r_refdef.viewcache.world_pvsbits)
5656                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5657         if (r_refdef.viewcache.world_leafvisible)
5658                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5659         if (r_refdef.viewcache.world_surfacevisible)
5660                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5661         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5662 }
5663
5664 void R_Main_ResizeViewCache(void)
5665 {
5666         int numentities = r_refdef.scene.numentities;
5667         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5668         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5669         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5670         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5671         if (r_refdef.viewcache.maxentities < numentities)
5672         {
5673                 r_refdef.viewcache.maxentities = numentities;
5674                 if (r_refdef.viewcache.entityvisible)
5675                         Mem_Free(r_refdef.viewcache.entityvisible);
5676                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5677         }
5678         if (r_refdef.viewcache.world_numclusters != numclusters)
5679         {
5680                 r_refdef.viewcache.world_numclusters = numclusters;
5681                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5682                 if (r_refdef.viewcache.world_pvsbits)
5683                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5684                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5685         }
5686         if (r_refdef.viewcache.world_numleafs != numleafs)
5687         {
5688                 r_refdef.viewcache.world_numleafs = numleafs;
5689                 if (r_refdef.viewcache.world_leafvisible)
5690                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5691                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5692         }
5693         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5694         {
5695                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5696                 if (r_refdef.viewcache.world_surfacevisible)
5697                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5698                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5699         }
5700 }
5701
5702 extern rtexture_t *loadingscreentexture;
5703 void gl_main_start(void)
5704 {
5705         loadingscreentexture = NULL;
5706         r_texture_blanknormalmap = NULL;
5707         r_texture_white = NULL;
5708         r_texture_grey128 = NULL;
5709         r_texture_black = NULL;
5710         r_texture_whitecube = NULL;
5711         r_texture_normalizationcube = NULL;
5712         r_texture_fogattenuation = NULL;
5713         r_texture_gammaramps = NULL;
5714
5715         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5716         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5717
5718         switch(vid.renderpath)
5719         {
5720         case RENDERPATH_GL20:
5721         case RENDERPATH_CGGL:
5722                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5723                 Cvar_SetValueQuick(&gl_combine, 1);
5724                 Cvar_SetValueQuick(&r_glsl, 1);
5725                 r_loadnormalmap = true;
5726                 r_loadgloss = true;
5727                 r_loadfog = false;
5728                 break;
5729         case RENDERPATH_GL13:
5730                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5731                 Cvar_SetValueQuick(&gl_combine, 1);
5732                 Cvar_SetValueQuick(&r_glsl, 0);
5733                 r_loadnormalmap = false;
5734                 r_loadgloss = false;
5735                 r_loadfog = true;
5736                 break;
5737         case RENDERPATH_GL11:
5738                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5739                 Cvar_SetValueQuick(&gl_combine, 0);
5740                 Cvar_SetValueQuick(&r_glsl, 0);
5741                 r_loadnormalmap = false;
5742                 r_loadgloss = false;
5743                 r_loadfog = true;
5744                 break;
5745         }
5746
5747         R_AnimCache_Free();
5748         R_FrameData_Reset();
5749
5750         r_numqueries = 0;
5751         r_maxqueries = 0;
5752         memset(r_queries, 0, sizeof(r_queries));
5753
5754         r_qwskincache = NULL;
5755         r_qwskincache_size = 0;
5756
5757         // set up r_skinframe loading system for textures
5758         memset(&r_skinframe, 0, sizeof(r_skinframe));
5759         r_skinframe.loadsequence = 1;
5760         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5761
5762         r_main_texturepool = R_AllocTexturePool();
5763         R_BuildBlankTextures();
5764         R_BuildNoTexture();
5765         if (vid.support.arb_texture_cube_map)
5766         {
5767                 R_BuildWhiteCube();
5768                 R_BuildNormalizationCube();
5769         }
5770         r_texture_fogattenuation = NULL;
5771         r_texture_gammaramps = NULL;
5772         //r_texture_fogintensity = NULL;
5773         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5774         memset(&r_waterstate, 0, sizeof(r_waterstate));
5775         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5776         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5777 #ifdef SUPPORTCG
5778         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5779         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5780 #endif
5781         memset(&r_svbsp, 0, sizeof (r_svbsp));
5782
5783         r_refdef.fogmasktable_density = 0;
5784 }
5785
5786 void gl_main_shutdown(void)
5787 {
5788         R_AnimCache_Free();
5789         R_FrameData_Reset();
5790
5791         R_Main_FreeViewCache();
5792
5793         if (r_maxqueries)
5794                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5795
5796         r_numqueries = 0;
5797         r_maxqueries = 0;
5798         memset(r_queries, 0, sizeof(r_queries));
5799
5800         r_qwskincache = NULL;
5801         r_qwskincache_size = 0;
5802
5803         // clear out the r_skinframe state
5804         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5805         memset(&r_skinframe, 0, sizeof(r_skinframe));
5806
5807         if (r_svbsp.nodes)
5808                 Mem_Free(r_svbsp.nodes);
5809         memset(&r_svbsp, 0, sizeof (r_svbsp));
5810         R_FreeTexturePool(&r_main_texturepool);
5811         loadingscreentexture = NULL;
5812         r_texture_blanknormalmap = NULL;
5813         r_texture_white = NULL;
5814         r_texture_grey128 = NULL;
5815         r_texture_black = NULL;
5816         r_texture_whitecube = NULL;
5817         r_texture_normalizationcube = NULL;
5818         r_texture_fogattenuation = NULL;
5819         r_texture_gammaramps = NULL;
5820         //r_texture_fogintensity = NULL;
5821         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5822         memset(&r_waterstate, 0, sizeof(r_waterstate));
5823         R_GLSL_Restart_f();
5824 }
5825
5826 extern void CL_ParseEntityLump(char *entitystring);
5827 void gl_main_newmap(void)
5828 {
5829         // FIXME: move this code to client
5830         int l;
5831         char *entities, entname[MAX_QPATH];
5832         if (r_qwskincache)
5833                 Mem_Free(r_qwskincache);
5834         r_qwskincache = NULL;
5835         r_qwskincache_size = 0;
5836         if (cl.worldmodel)
5837         {
5838                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5839                 l = (int)strlen(entname) - 4;
5840                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5841                 {
5842                         memcpy(entname + l, ".ent", 5);
5843                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5844                         {
5845                                 CL_ParseEntityLump(entities);
5846                                 Mem_Free(entities);
5847                                 return;
5848                         }
5849                 }
5850                 if (cl.worldmodel->brush.entities)
5851                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5852         }
5853         R_Main_FreeViewCache();
5854
5855         R_FrameData_Reset();
5856 }
5857
5858 void GL_Main_Init(void)
5859 {
5860         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5861
5862         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5863         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5864         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5865         if (gamemode == GAME_NEHAHRA)
5866         {
5867                 Cvar_RegisterVariable (&gl_fogenable);
5868                 Cvar_RegisterVariable (&gl_fogdensity);
5869                 Cvar_RegisterVariable (&gl_fogred);
5870                 Cvar_RegisterVariable (&gl_foggreen);
5871                 Cvar_RegisterVariable (&gl_fogblue);
5872                 Cvar_RegisterVariable (&gl_fogstart);
5873                 Cvar_RegisterVariable (&gl_fogend);
5874                 Cvar_RegisterVariable (&gl_skyclip);
5875         }
5876         Cvar_RegisterVariable(&r_motionblur);
5877         Cvar_RegisterVariable(&r_motionblur_maxblur);
5878         Cvar_RegisterVariable(&r_motionblur_bmin);
5879         Cvar_RegisterVariable(&r_motionblur_vmin);
5880         Cvar_RegisterVariable(&r_motionblur_vmax);
5881         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5882         Cvar_RegisterVariable(&r_motionblur_randomize);
5883         Cvar_RegisterVariable(&r_damageblur);
5884         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5885         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5886         Cvar_RegisterVariable(&r_equalize_entities_by);
5887         Cvar_RegisterVariable(&r_equalize_entities_to);
5888         Cvar_RegisterVariable(&r_depthfirst);
5889         Cvar_RegisterVariable(&r_useinfinitefarclip);
5890         Cvar_RegisterVariable(&r_farclip_base);
5891         Cvar_RegisterVariable(&r_farclip_world);
5892         Cvar_RegisterVariable(&r_nearclip);
5893         Cvar_RegisterVariable(&r_showbboxes);
5894         Cvar_RegisterVariable(&r_showsurfaces);
5895         Cvar_RegisterVariable(&r_showtris);
5896         Cvar_RegisterVariable(&r_shownormals);
5897         Cvar_RegisterVariable(&r_showlighting);
5898         Cvar_RegisterVariable(&r_showshadowvolumes);
5899         Cvar_RegisterVariable(&r_showcollisionbrushes);
5900         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5901         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5902         Cvar_RegisterVariable(&r_showdisabledepthtest);
5903         Cvar_RegisterVariable(&r_drawportals);
5904         Cvar_RegisterVariable(&r_drawentities);
5905         Cvar_RegisterVariable(&r_cullentities_trace);
5906         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5907         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5908         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5909         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5910         Cvar_RegisterVariable(&r_drawviewmodel);
5911         Cvar_RegisterVariable(&r_speeds);
5912         Cvar_RegisterVariable(&r_fullbrights);
5913         Cvar_RegisterVariable(&r_wateralpha);
5914         Cvar_RegisterVariable(&r_dynamic);
5915         Cvar_RegisterVariable(&r_fullbright);
5916         Cvar_RegisterVariable(&r_shadows);
5917         Cvar_RegisterVariable(&r_shadows_darken);
5918         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5919         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5920         Cvar_RegisterVariable(&r_shadows_throwdistance);
5921         Cvar_RegisterVariable(&r_shadows_throwdirection);
5922         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5923         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5924         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5925         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5926         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5927         Cvar_RegisterVariable(&r_fog_exp2);
5928         Cvar_RegisterVariable(&r_drawfog);
5929         Cvar_RegisterVariable(&r_transparentdepthmasking);
5930         Cvar_RegisterVariable(&r_texture_dds_load);
5931         Cvar_RegisterVariable(&r_texture_dds_save);
5932         Cvar_RegisterVariable(&r_textureunits);
5933         Cvar_RegisterVariable(&gl_combine);
5934         Cvar_RegisterVariable(&r_glsl);
5935         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5936         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5937         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5938         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5939         Cvar_RegisterVariable(&r_glsl_postprocess);
5940         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5941         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5942         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5943         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5944         Cvar_RegisterVariable(&r_water);
5945         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5946         Cvar_RegisterVariable(&r_water_clippingplanebias);
5947         Cvar_RegisterVariable(&r_water_refractdistort);
5948         Cvar_RegisterVariable(&r_water_reflectdistort);
5949         Cvar_RegisterVariable(&r_lerpsprites);
5950         Cvar_RegisterVariable(&r_lerpmodels);
5951         Cvar_RegisterVariable(&r_lerplightstyles);
5952         Cvar_RegisterVariable(&r_waterscroll);
5953         Cvar_RegisterVariable(&r_bloom);
5954         Cvar_RegisterVariable(&r_bloom_colorscale);
5955         Cvar_RegisterVariable(&r_bloom_brighten);
5956         Cvar_RegisterVariable(&r_bloom_blur);
5957         Cvar_RegisterVariable(&r_bloom_resolution);
5958         Cvar_RegisterVariable(&r_bloom_colorexponent);
5959         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5960         Cvar_RegisterVariable(&r_hdr);
5961         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5962         Cvar_RegisterVariable(&r_hdr_glowintensity);
5963         Cvar_RegisterVariable(&r_hdr_range);
5964         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5965         Cvar_RegisterVariable(&developer_texturelogging);
5966         Cvar_RegisterVariable(&gl_lightmaps);
5967         Cvar_RegisterVariable(&r_test);
5968         Cvar_RegisterVariable(&r_batchmode);
5969         Cvar_RegisterVariable(&r_glsl_saturation);
5970         Cvar_RegisterVariable(&r_framedatasize);
5971         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5972                 Cvar_SetValue("r_fullbrights", 0);
5973         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5974
5975         Cvar_RegisterVariable(&r_track_sprites);
5976         Cvar_RegisterVariable(&r_track_sprites_flags);
5977         Cvar_RegisterVariable(&r_track_sprites_scalew);
5978         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5979 }
5980
5981 extern void R_Textures_Init(void);
5982 extern void GL_Draw_Init(void);
5983 extern void GL_Main_Init(void);
5984 extern void R_Shadow_Init(void);
5985 extern void R_Sky_Init(void);
5986 extern void GL_Surf_Init(void);
5987 extern void R_Particles_Init(void);
5988 extern void R_Explosion_Init(void);
5989 extern void gl_backend_init(void);
5990 extern void Sbar_Init(void);
5991 extern void R_LightningBeams_Init(void);
5992 extern void Mod_RenderInit(void);
5993 extern void Font_Init(void);
5994
5995 void Render_Init(void)
5996 {
5997         gl_backend_init();
5998         R_Textures_Init();
5999         GL_Main_Init();
6000         Font_Init();
6001         GL_Draw_Init();
6002         R_Shadow_Init();
6003         R_Sky_Init();
6004         GL_Surf_Init();
6005         Sbar_Init();
6006         R_Particles_Init();
6007         R_Explosion_Init();
6008         R_LightningBeams_Init();
6009         Mod_RenderInit();
6010 }
6011
6012 /*
6013 ===============
6014 GL_Init
6015 ===============
6016 */
6017 extern char *ENGINE_EXTENSIONS;
6018 void GL_Init (void)
6019 {
6020         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6021         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6022         gl_version = (const char *)qglGetString(GL_VERSION);
6023         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6024
6025         if (!gl_extensions)
6026                 gl_extensions = "";
6027         if (!gl_platformextensions)
6028                 gl_platformextensions = "";
6029
6030         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6031         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6032         Con_Printf("GL_VERSION: %s\n", gl_version);
6033         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6034         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6035
6036         VID_CheckExtensions();
6037
6038         // LordHavoc: report supported extensions
6039         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6040
6041         // clear to black (loading plaque will be seen over this)
6042         CHECKGLERROR
6043         qglClearColor(0,0,0,1);CHECKGLERROR
6044         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6045 }
6046
6047 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6048 {
6049         int i;
6050         mplane_t *p;
6051         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6052         {
6053                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6054                 if (i == 4)
6055                         continue;
6056                 p = r_refdef.view.frustum + i;
6057                 switch(p->signbits)
6058                 {
6059                 default:
6060                 case 0:
6061                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6062                                 return true;
6063                         break;
6064                 case 1:
6065                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6066                                 return true;
6067                         break;
6068                 case 2:
6069                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6070                                 return true;
6071                         break;
6072                 case 3:
6073                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6074                                 return true;
6075                         break;
6076                 case 4:
6077                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6078                                 return true;
6079                         break;
6080                 case 5:
6081                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6082                                 return true;
6083                         break;
6084                 case 6:
6085                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6086                                 return true;
6087                         break;
6088                 case 7:
6089                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6090                                 return true;
6091                         break;
6092                 }
6093         }
6094         return false;
6095 }
6096
6097 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6098 {
6099         int i;
6100         const mplane_t *p;
6101         for (i = 0;i < numplanes;i++)
6102         {
6103                 p = planes + i;
6104                 switch(p->signbits)
6105                 {
6106                 default:
6107                 case 0:
6108                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6109                                 return true;
6110                         break;
6111                 case 1:
6112                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6113                                 return true;
6114                         break;
6115                 case 2:
6116                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6117                                 return true;
6118                         break;
6119                 case 3:
6120                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6121                                 return true;
6122                         break;
6123                 case 4:
6124                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6125                                 return true;
6126                         break;
6127                 case 5:
6128                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6129                                 return true;
6130                         break;
6131                 case 6:
6132                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6133                                 return true;
6134                         break;
6135                 case 7:
6136                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6137                                 return true;
6138                         break;
6139                 }
6140         }
6141         return false;
6142 }
6143
6144 //==================================================================================
6145
6146 // LordHavoc: this stores temporary data used within the same frame
6147
6148 qboolean r_framedata_failed;
6149 static size_t r_framedata_size;
6150 static size_t r_framedata_current;
6151 static void *r_framedata_base;
6152
6153 void R_FrameData_Reset(void)
6154 {
6155         if (r_framedata_base)
6156                 Mem_Free(r_framedata_base);
6157         r_framedata_base = NULL;
6158         r_framedata_size = 0;
6159         r_framedata_current = 0;
6160         r_framedata_failed = false;
6161 }
6162
6163 void R_FrameData_NewFrame(void)
6164 {
6165         size_t wantedsize;
6166         if (r_framedata_failed)
6167                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6168         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6169         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6170         if (r_framedata_size != wantedsize)
6171         {
6172                 r_framedata_size = wantedsize;
6173                 if (r_framedata_base)
6174                         Mem_Free(r_framedata_base);
6175                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6176         }
6177         r_framedata_current = 0;
6178         r_framedata_failed = false;
6179 }
6180
6181 void *R_FrameData_Alloc(size_t size)
6182 {
6183         void *data;
6184
6185         // align to 16 byte boundary
6186         size = (size + 15) & ~15;
6187         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6188         r_framedata_current += size;
6189
6190         // check overflow
6191         if (r_framedata_current > r_framedata_size)
6192                 r_framedata_failed = true;
6193
6194         // return NULL on everything after a failure
6195         if (r_framedata_failed)
6196                 return NULL;
6197
6198         return data;
6199 }
6200
6201 void *R_FrameData_Store(size_t size, void *data)
6202 {
6203         void *d = R_FrameData_Alloc(size);
6204         if (d)
6205                 memcpy(d, data, size);
6206         return d;
6207 }
6208
6209 //==================================================================================
6210
6211 // LordHavoc: animcache originally written by Echon, rewritten since then
6212
6213 /**
6214  * Animation cache prevents re-generating mesh data for an animated model
6215  * multiple times in one frame for lighting, shadowing, reflections, etc.
6216  */
6217
6218 void R_AnimCache_Free(void)
6219 {
6220 }
6221
6222 void R_AnimCache_ClearCache(void)
6223 {
6224         int i;
6225         entity_render_t *ent;
6226
6227         for (i = 0;i < r_refdef.scene.numentities;i++)
6228         {
6229                 ent = r_refdef.scene.entities[i];
6230                 ent->animcache_vertex3f = NULL;
6231                 ent->animcache_normal3f = NULL;
6232                 ent->animcache_svector3f = NULL;
6233                 ent->animcache_tvector3f = NULL;
6234         }
6235 }
6236
6237 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6238 {
6239         dp_model_t *model = ent->model;
6240         int numvertices;
6241         // see if it's already cached this frame
6242         if (ent->animcache_vertex3f)
6243         {
6244                 // add normals/tangents if needed
6245                 if (wantnormals || wanttangents)
6246                 {
6247                         if (ent->animcache_normal3f)
6248                                 wantnormals = false;
6249                         if (ent->animcache_svector3f)
6250                                 wanttangents = false;
6251                         if (wantnormals || wanttangents)
6252                         {
6253                                 numvertices = model->surfmesh.num_vertices;
6254                                 if (wantnormals)
6255                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6256                                 if (wanttangents)
6257                                 {
6258                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6259                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6260                                 }
6261                                 if (!r_framedata_failed)
6262                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6263                         }
6264                 }
6265         }
6266         else
6267         {
6268                 // see if this ent is worth caching
6269                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6270                         return false;
6271                 // get some memory for this entity and generate mesh data
6272                 numvertices = model->surfmesh.num_vertices;
6273                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6274                 if (wantnormals)
6275                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6276                 if (wanttangents)
6277                 {
6278                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6279                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6280                 }
6281                 if (!r_framedata_failed)
6282                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6283         }
6284         return !r_framedata_failed;
6285 }
6286
6287 void R_AnimCache_CacheVisibleEntities(void)
6288 {
6289         int i;
6290         qboolean wantnormals = !r_showsurfaces.integer;
6291         qboolean wanttangents = !r_showsurfaces.integer;
6292
6293         switch(vid.renderpath)
6294         {
6295         case RENDERPATH_GL20:
6296         case RENDERPATH_CGGL:
6297                 break;
6298         case RENDERPATH_GL13:
6299         case RENDERPATH_GL11:
6300                 wanttangents = false;
6301                 break;
6302         }
6303
6304         // TODO: thread this
6305         // NOTE: R_PrepareRTLights() also caches entities
6306
6307         for (i = 0;i < r_refdef.scene.numentities;i++)
6308                 if (r_refdef.viewcache.entityvisible[i])
6309                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6310
6311         if (r_shadows.integer)
6312                 for (i = 0;i < r_refdef.scene.numentities;i++)
6313                         if (!r_refdef.viewcache.entityvisible[i])
6314                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6315 }
6316
6317 //==================================================================================
6318
6319 static void R_View_UpdateEntityLighting (void)
6320 {
6321         int i;
6322         entity_render_t *ent;
6323         vec3_t tempdiffusenormal, avg;
6324         vec_t f, fa, fd, fdd;
6325
6326         for (i = 0;i < r_refdef.scene.numentities;i++)
6327         {
6328                 ent = r_refdef.scene.entities[i];
6329
6330                 // skip unseen models
6331                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6332                         continue;
6333
6334                 // skip bsp models
6335                 if (ent->model && ent->model->brush.num_leafs)
6336                 {
6337                         // TODO: use modellight for r_ambient settings on world?
6338                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6339                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6340                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6341                         continue;
6342                 }
6343
6344                 // fetch the lighting from the worldmodel data
6345                 VectorClear(ent->modellight_ambient);
6346                 VectorClear(ent->modellight_diffuse);
6347                 VectorClear(tempdiffusenormal);
6348                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6349                 {
6350                         vec3_t org;
6351                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6352                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6353                         if(ent->flags & RENDER_EQUALIZE)
6354                         {
6355                                 // first fix up ambient lighting...
6356                                 if(r_equalize_entities_minambient.value > 0)
6357                                 {
6358                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6359                                         if(fd > 0)
6360                                         {
6361                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6362                                                 if(fa < r_equalize_entities_minambient.value * fd)
6363                                                 {
6364                                                         // solve:
6365                                                         //   fa'/fd' = minambient
6366                                                         //   fa'+0.25*fd' = fa+0.25*fd
6367                                                         //   ...
6368                                                         //   fa' = fd' * minambient
6369                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6370                                                         //   ...
6371                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6372                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6373                                                         //   ...
6374                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6375                                                         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
6376                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6377                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6378                                                 }
6379                                         }
6380                                 }
6381
6382                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6383                                 {
6384                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6385                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6386                                         if(f > 0)
6387                                         {
6388                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6389                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6390                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6391                                         }
6392                                 }
6393                         }
6394                 }
6395                 else // highly rare
6396                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6397
6398                 // move the light direction into modelspace coordinates for lighting code
6399                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6400                 if(VectorLength2(ent->modellight_lightdir) == 0)
6401                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6402                 VectorNormalize(ent->modellight_lightdir);
6403         }
6404 }
6405
6406 #define MAX_LINEOFSIGHTTRACES 64
6407
6408 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6409 {
6410         int i;
6411         vec3_t boxmins, boxmaxs;
6412         vec3_t start;
6413         vec3_t end;
6414         dp_model_t *model = r_refdef.scene.worldmodel;
6415
6416         if (!model || !model->brush.TraceLineOfSight)
6417                 return true;
6418
6419         // expand the box a little
6420         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6421         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6422         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6423         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6424         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6425         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6426
6427         // try center
6428         VectorCopy(eye, start);
6429         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6430         if (model->brush.TraceLineOfSight(model, start, end))
6431                 return true;
6432
6433         // try various random positions
6434         for (i = 0;i < numsamples;i++)
6435         {
6436                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6437                 if (model->brush.TraceLineOfSight(model, start, end))
6438                         return true;
6439         }
6440
6441         return false;
6442 }
6443
6444
6445 static void R_View_UpdateEntityVisible (void)
6446 {
6447         int i;
6448         int renderimask;
6449         int samples;
6450         entity_render_t *ent;
6451
6452         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6453         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6454         {
6455                 // worldmodel can check visibility
6456                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6457                 for (i = 0;i < r_refdef.scene.numentities;i++)
6458                 {
6459                         ent = r_refdef.scene.entities[i];
6460                         if (!(ent->flags & renderimask))
6461                         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)))
6462                         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))
6463                                 r_refdef.viewcache.entityvisible[i] = true;
6464                 }
6465                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6466                 {
6467                         for (i = 0;i < r_refdef.scene.numentities;i++)
6468                         {
6469                                 ent = r_refdef.scene.entities[i];
6470                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6471                                 {
6472                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6473                                         if (samples < 0)
6474                                                 continue; // temp entities do pvs only
6475                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6476                                                 ent->last_trace_visibility = realtime;
6477                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6478                                                 r_refdef.viewcache.entityvisible[i] = 0;
6479                                 }
6480                         }
6481                 }
6482         }
6483         else
6484         {
6485                 // no worldmodel or it can't check visibility
6486                 for (i = 0;i < r_refdef.scene.numentities;i++)
6487                 {
6488                         ent = r_refdef.scene.entities[i];
6489                         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));
6490                 }
6491         }
6492 }
6493
6494 /// only used if skyrendermasked, and normally returns false
6495 int R_DrawBrushModelsSky (void)
6496 {
6497         int i, sky;
6498         entity_render_t *ent;
6499
6500         sky = false;
6501         for (i = 0;i < r_refdef.scene.numentities;i++)
6502         {
6503                 if (!r_refdef.viewcache.entityvisible[i])
6504                         continue;
6505                 ent = r_refdef.scene.entities[i];
6506                 if (!ent->model || !ent->model->DrawSky)
6507                         continue;
6508                 ent->model->DrawSky(ent);
6509                 sky = true;
6510         }
6511         return sky;
6512 }
6513
6514 static void R_DrawNoModel(entity_render_t *ent);
6515 static void R_DrawModels(void)
6516 {
6517         int i;
6518         entity_render_t *ent;
6519
6520         for (i = 0;i < r_refdef.scene.numentities;i++)
6521         {
6522                 if (!r_refdef.viewcache.entityvisible[i])
6523                         continue;
6524                 ent = r_refdef.scene.entities[i];
6525                 r_refdef.stats.entities++;
6526                 if (ent->model && ent->model->Draw != NULL)
6527                         ent->model->Draw(ent);
6528                 else
6529                         R_DrawNoModel(ent);
6530         }
6531 }
6532
6533 static void R_DrawModelsDepth(void)
6534 {
6535         int i;
6536         entity_render_t *ent;
6537
6538         for (i = 0;i < r_refdef.scene.numentities;i++)
6539         {
6540                 if (!r_refdef.viewcache.entityvisible[i])
6541                         continue;
6542                 ent = r_refdef.scene.entities[i];
6543                 if (ent->model && ent->model->DrawDepth != NULL)
6544                         ent->model->DrawDepth(ent);
6545         }
6546 }
6547
6548 static void R_DrawModelsDebug(void)
6549 {
6550         int i;
6551         entity_render_t *ent;
6552
6553         for (i = 0;i < r_refdef.scene.numentities;i++)
6554         {
6555                 if (!r_refdef.viewcache.entityvisible[i])
6556                         continue;
6557                 ent = r_refdef.scene.entities[i];
6558                 if (ent->model && ent->model->DrawDebug != NULL)
6559                         ent->model->DrawDebug(ent);
6560         }
6561 }
6562
6563 static void R_DrawModelsAddWaterPlanes(void)
6564 {
6565         int i;
6566         entity_render_t *ent;
6567
6568         for (i = 0;i < r_refdef.scene.numentities;i++)
6569         {
6570                 if (!r_refdef.viewcache.entityvisible[i])
6571                         continue;
6572                 ent = r_refdef.scene.entities[i];
6573                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6574                         ent->model->DrawAddWaterPlanes(ent);
6575         }
6576 }
6577
6578 static void R_View_SetFrustum(void)
6579 {
6580         int i;
6581         double slopex, slopey;
6582         vec3_t forward, left, up, origin;
6583
6584         // we can't trust r_refdef.view.forward and friends in reflected scenes
6585         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6586
6587 #if 0
6588         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6589         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6590         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6591         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6592         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6593         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6594         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6595         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6596         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6597         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6598         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6599         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6600 #endif
6601
6602 #if 0
6603         zNear = r_refdef.nearclip;
6604         nudge = 1.0 - 1.0 / (1<<23);
6605         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6606         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6607         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6608         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6609         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6610         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6611         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6612         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6613 #endif
6614
6615
6616
6617 #if 0
6618         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6619         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6620         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6621         r_refdef.view.frustum[0].dist = m[15] - m[12];
6622
6623         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6624         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6625         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6626         r_refdef.view.frustum[1].dist = m[15] + m[12];
6627
6628         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6629         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6630         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6631         r_refdef.view.frustum[2].dist = m[15] - m[13];
6632
6633         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6634         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6635         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6636         r_refdef.view.frustum[3].dist = m[15] + m[13];
6637
6638         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6639         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6640         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6641         r_refdef.view.frustum[4].dist = m[15] - m[14];
6642
6643         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6644         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6645         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6646         r_refdef.view.frustum[5].dist = m[15] + m[14];
6647 #endif
6648
6649         if (r_refdef.view.useperspective)
6650         {
6651                 slopex = 1.0 / r_refdef.view.frustum_x;
6652                 slopey = 1.0 / r_refdef.view.frustum_y;
6653                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6654                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6655                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6656                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6657                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6658
6659                 // Leaving those out was a mistake, those were in the old code, and they
6660                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6661                 // I couldn't reproduce it after adding those normalizations. --blub
6662                 VectorNormalize(r_refdef.view.frustum[0].normal);
6663                 VectorNormalize(r_refdef.view.frustum[1].normal);
6664                 VectorNormalize(r_refdef.view.frustum[2].normal);
6665                 VectorNormalize(r_refdef.view.frustum[3].normal);
6666
6667                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6668                 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]);
6669                 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]);
6670                 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]);
6671                 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]);
6672
6673                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6674                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6675                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6676                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6677                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6678         }
6679         else
6680         {
6681                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6682                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6683                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6684                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6685                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6686                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6687                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6688                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6689                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6690                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6691         }
6692         r_refdef.view.numfrustumplanes = 5;
6693
6694         if (r_refdef.view.useclipplane)
6695         {
6696                 r_refdef.view.numfrustumplanes = 6;
6697                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6698         }
6699
6700         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6701                 PlaneClassify(r_refdef.view.frustum + i);
6702
6703         // LordHavoc: note to all quake engine coders, Quake had a special case
6704         // for 90 degrees which assumed a square view (wrong), so I removed it,
6705         // Quake2 has it disabled as well.
6706
6707         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6708         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6709         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6710         //PlaneClassify(&frustum[0]);
6711
6712         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6713         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6714         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6715         //PlaneClassify(&frustum[1]);
6716
6717         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6718         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6719         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6720         //PlaneClassify(&frustum[2]);
6721
6722         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6723         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6724         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6725         //PlaneClassify(&frustum[3]);
6726
6727         // nearclip plane
6728         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6729         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6730         //PlaneClassify(&frustum[4]);
6731 }
6732
6733 void R_View_Update(void)
6734 {
6735         R_Main_ResizeViewCache();
6736         R_View_SetFrustum();
6737         R_View_WorldVisibility(r_refdef.view.useclipplane);
6738         R_View_UpdateEntityVisible();
6739         R_View_UpdateEntityLighting();
6740 }
6741
6742 void R_SetupView(qboolean allowwaterclippingplane)
6743 {
6744         const float *customclipplane = NULL;
6745         float plane[4];
6746         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6747         {
6748                 // LordHavoc: couldn't figure out how to make this approach the
6749                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6750                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6751                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6752                         dist = r_refdef.view.clipplane.dist;
6753                 plane[0] = r_refdef.view.clipplane.normal[0];
6754                 plane[1] = r_refdef.view.clipplane.normal[1];
6755                 plane[2] = r_refdef.view.clipplane.normal[2];
6756                 plane[3] = dist;
6757                 customclipplane = plane;
6758         }
6759
6760         if (!r_refdef.view.useperspective)
6761                 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);
6762         else if (vid.stencil && r_useinfinitefarclip.integer)
6763                 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);
6764         else
6765                 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);
6766         R_SetViewport(&r_refdef.view.viewport);
6767 }
6768
6769 void R_EntityMatrix(const matrix4x4_t *matrix)
6770 {
6771         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6772         {
6773                 gl_modelmatrixchanged = false;
6774                 gl_modelmatrix = *matrix;
6775                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6776                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6777                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6778                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6779                 CHECKGLERROR
6780                 switch(vid.renderpath)
6781                 {
6782                 case RENDERPATH_GL20:
6783                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6784                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6785                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6786                         break;
6787                 case RENDERPATH_CGGL:
6788 #ifdef SUPPORTCG
6789                         CHECKCGERROR
6790                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6791                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6792                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6793 #endif
6794                         break;
6795                 case RENDERPATH_GL13:
6796                 case RENDERPATH_GL11:
6797                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6798                         break;
6799                 }
6800         }
6801 }
6802
6803 void R_ResetViewRendering2D(void)
6804 {
6805         r_viewport_t viewport;
6806         DrawQ_Finish();
6807
6808         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6809         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);
6810         R_SetViewport(&viewport);
6811         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6812         GL_Color(1, 1, 1, 1);
6813         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6814         GL_BlendFunc(GL_ONE, GL_ZERO);
6815         GL_AlphaTest(false);
6816         GL_ScissorTest(false);
6817         GL_DepthMask(false);
6818         GL_DepthRange(0, 1);
6819         GL_DepthTest(false);
6820         R_EntityMatrix(&identitymatrix);
6821         R_Mesh_ResetTextureState();
6822         GL_PolygonOffset(0, 0);
6823         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6824         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6825         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6826         qglStencilMask(~0);CHECKGLERROR
6827         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6828         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6829         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6830 }
6831
6832 void R_ResetViewRendering3D(void)
6833 {
6834         DrawQ_Finish();
6835
6836         R_SetupView(true);
6837         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6838         GL_Color(1, 1, 1, 1);
6839         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6840         GL_BlendFunc(GL_ONE, GL_ZERO);
6841         GL_AlphaTest(false);
6842         GL_ScissorTest(true);
6843         GL_DepthMask(true);
6844         GL_DepthRange(0, 1);
6845         GL_DepthTest(true);
6846         R_EntityMatrix(&identitymatrix);
6847         R_Mesh_ResetTextureState();
6848         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6849         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6850         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6851         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6852         qglStencilMask(~0);CHECKGLERROR
6853         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6854         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6855         GL_CullFace(r_refdef.view.cullface_back);
6856 }
6857
6858 void R_RenderScene(void);
6859 void R_RenderWaterPlanes(void);
6860
6861 static void R_Water_StartFrame(void)
6862 {
6863         int i;
6864         int waterwidth, waterheight, texturewidth, textureheight;
6865         r_waterstate_waterplane_t *p;
6866
6867         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6868                 return;
6869
6870         switch(vid.renderpath)
6871         {
6872         case RENDERPATH_GL20:
6873         case RENDERPATH_CGGL:
6874                 break;
6875         case RENDERPATH_GL13:
6876         case RENDERPATH_GL11:
6877                 return;
6878         }
6879
6880         // set waterwidth and waterheight to the water resolution that will be
6881         // used (often less than the screen resolution for faster rendering)
6882         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6883         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6884
6885         // calculate desired texture sizes
6886         // can't use water if the card does not support the texture size
6887         if (!r_water.integer || r_showsurfaces.integer)
6888                 texturewidth = textureheight = waterwidth = waterheight = 0;
6889         else if (vid.support.arb_texture_non_power_of_two)
6890         {
6891                 texturewidth = waterwidth;
6892                 textureheight = waterheight;
6893         }
6894         else
6895         {
6896                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6897                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6898         }
6899
6900         // allocate textures as needed
6901         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6902         {
6903                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6904                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6905                 {
6906                         if (p->texture_refraction)
6907                                 R_FreeTexture(p->texture_refraction);
6908                         p->texture_refraction = NULL;
6909                         if (p->texture_reflection)
6910                                 R_FreeTexture(p->texture_reflection);
6911                         p->texture_reflection = NULL;
6912                 }
6913                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6914                 r_waterstate.texturewidth = texturewidth;
6915                 r_waterstate.textureheight = textureheight;
6916         }
6917
6918         if (r_waterstate.texturewidth)
6919         {
6920                 r_waterstate.enabled = true;
6921
6922                 // when doing a reduced render (HDR) we want to use a smaller area
6923                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6924                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6925
6926                 // set up variables that will be used in shader setup
6927                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6928                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6929                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6930                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6931         }
6932
6933         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6934         r_waterstate.numwaterplanes = 0;
6935 }
6936
6937 void R_Water_AddWaterPlane(msurface_t *surface)
6938 {
6939         int triangleindex, planeindex;
6940         const int *e;
6941         vec3_t vert[3];
6942         vec3_t normal;
6943         vec3_t center;
6944         mplane_t plane;
6945         r_waterstate_waterplane_t *p;
6946         texture_t *t = R_GetCurrentTexture(surface->texture);
6947         // just use the first triangle with a valid normal for any decisions
6948         VectorClear(normal);
6949         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6950         {
6951                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6952                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6953                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6954                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6955                 if (VectorLength2(normal) >= 0.001)
6956                         break;
6957         }
6958
6959         VectorCopy(normal, plane.normal);
6960         VectorNormalize(plane.normal);
6961         plane.dist = DotProduct(vert[0], plane.normal);
6962         PlaneClassify(&plane);
6963         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6964         {
6965                 // skip backfaces (except if nocullface is set)
6966                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6967                         return;
6968                 VectorNegate(plane.normal, plane.normal);
6969                 plane.dist *= -1;
6970                 PlaneClassify(&plane);
6971         }
6972
6973
6974         // find a matching plane if there is one
6975         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6976                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6977                         break;
6978         if (planeindex >= r_waterstate.maxwaterplanes)
6979                 return; // nothing we can do, out of planes
6980
6981         // if this triangle does not fit any known plane rendered this frame, add one
6982         if (planeindex >= r_waterstate.numwaterplanes)
6983         {
6984                 // store the new plane
6985                 r_waterstate.numwaterplanes++;
6986                 p->plane = plane;
6987                 // clear materialflags and pvs
6988                 p->materialflags = 0;
6989                 p->pvsvalid = false;
6990         }
6991         // merge this surface's materialflags into the waterplane
6992         p->materialflags |= t->currentmaterialflags;
6993         // merge this surface's PVS into the waterplane
6994         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6995         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6996          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6997         {
6998                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6999                 p->pvsvalid = true;
7000         }
7001 }
7002
7003 static void R_Water_ProcessPlanes(void)
7004 {
7005         r_refdef_view_t originalview;
7006         r_refdef_view_t myview;
7007         int planeindex;
7008         r_waterstate_waterplane_t *p;
7009
7010         originalview = r_refdef.view;
7011
7012         // make sure enough textures are allocated
7013         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7014         {
7015                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7016                 {
7017                         if (!p->texture_refraction)
7018                                 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);
7019                         if (!p->texture_refraction)
7020                                 goto error;
7021                 }
7022
7023                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7024                 {
7025                         if (!p->texture_reflection)
7026                                 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);
7027                         if (!p->texture_reflection)
7028                                 goto error;
7029                 }
7030         }
7031
7032         // render views
7033         r_refdef.view = originalview;
7034         r_refdef.view.showdebug = false;
7035         r_refdef.view.width = r_waterstate.waterwidth;
7036         r_refdef.view.height = r_waterstate.waterheight;
7037         r_refdef.view.useclipplane = true;
7038         myview = r_refdef.view;
7039         r_waterstate.renderingscene = true;
7040         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7041         {
7042                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7043                 {
7044                         r_refdef.view = myview;
7045                         // render reflected scene and copy into texture
7046                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7047                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7048                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7049                         r_refdef.view.clipplane = p->plane;
7050                         // reverse the cullface settings for this render
7051                         r_refdef.view.cullface_front = GL_FRONT;
7052                         r_refdef.view.cullface_back = GL_BACK;
7053                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7054                         {
7055                                 r_refdef.view.usecustompvs = true;
7056                                 if (p->pvsvalid)
7057                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7058                                 else
7059                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7060                         }
7061
7062                         R_ResetViewRendering3D();
7063                         R_ClearScreen(r_refdef.fogenabled);
7064                         R_View_Update();
7065                         R_RenderScene();
7066
7067                         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);
7068                 }
7069
7070                 // render the normal view scene and copy into texture
7071                 // (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)
7072                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7073                 {
7074                         r_refdef.view = myview;
7075                         r_refdef.view.clipplane = p->plane;
7076                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7077                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7078                         PlaneClassify(&r_refdef.view.clipplane);
7079
7080                         R_ResetViewRendering3D();
7081                         R_ClearScreen(r_refdef.fogenabled);
7082                         R_View_Update();
7083                         R_RenderScene();
7084
7085                         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);
7086                 }
7087
7088         }
7089         r_waterstate.renderingscene = false;
7090         r_refdef.view = originalview;
7091         R_ResetViewRendering3D();
7092         R_ClearScreen(r_refdef.fogenabled);
7093         R_View_Update();
7094         return;
7095 error:
7096         r_refdef.view = originalview;
7097         r_waterstate.renderingscene = false;
7098         Cvar_SetValueQuick(&r_water, 0);
7099         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7100         return;
7101 }
7102
7103 void R_Bloom_StartFrame(void)
7104 {
7105         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7106
7107         switch(vid.renderpath)
7108         {
7109         case RENDERPATH_GL20:
7110         case RENDERPATH_CGGL:
7111                 break;
7112         case RENDERPATH_GL13:
7113         case RENDERPATH_GL11:
7114                 return;
7115         }
7116
7117         // set bloomwidth and bloomheight to the bloom resolution that will be
7118         // used (often less than the screen resolution for faster rendering)
7119         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7120         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7121         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7122         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7123         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7124
7125         // calculate desired texture sizes
7126         if (vid.support.arb_texture_non_power_of_two)
7127         {
7128                 screentexturewidth = r_refdef.view.width;
7129                 screentextureheight = r_refdef.view.height;
7130                 bloomtexturewidth = r_bloomstate.bloomwidth;
7131                 bloomtextureheight = r_bloomstate.bloomheight;
7132         }
7133         else
7134         {
7135                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7136                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7137                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7138                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7139         }
7140
7141         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))
7142         {
7143                 Cvar_SetValueQuick(&r_hdr, 0);
7144                 Cvar_SetValueQuick(&r_bloom, 0);
7145                 Cvar_SetValueQuick(&r_motionblur, 0);
7146                 Cvar_SetValueQuick(&r_damageblur, 0);
7147         }
7148
7149         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)))
7150                 screentexturewidth = screentextureheight = 0;
7151         if (!r_hdr.integer && !r_bloom.integer)
7152                 bloomtexturewidth = bloomtextureheight = 0;
7153
7154         // allocate textures as needed
7155         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7156         {
7157                 if (r_bloomstate.texture_screen)
7158                         R_FreeTexture(r_bloomstate.texture_screen);
7159                 r_bloomstate.texture_screen = NULL;
7160                 r_bloomstate.screentexturewidth = screentexturewidth;
7161                 r_bloomstate.screentextureheight = screentextureheight;
7162                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7163                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7164         }
7165         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7166         {
7167                 if (r_bloomstate.texture_bloom)
7168                         R_FreeTexture(r_bloomstate.texture_bloom);
7169                 r_bloomstate.texture_bloom = NULL;
7170                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7171                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7172                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7173                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7174         }
7175
7176         // when doing a reduced render (HDR) we want to use a smaller area
7177         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7178         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7179         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7180         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7181         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7182
7183         // set up a texcoord array for the full resolution screen image
7184         // (we have to keep this around to copy back during final render)
7185         r_bloomstate.screentexcoord2f[0] = 0;
7186         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7187         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7188         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7189         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7190         r_bloomstate.screentexcoord2f[5] = 0;
7191         r_bloomstate.screentexcoord2f[6] = 0;
7192         r_bloomstate.screentexcoord2f[7] = 0;
7193
7194         // set up a texcoord array for the reduced resolution bloom image
7195         // (which will be additive blended over the screen image)
7196         r_bloomstate.bloomtexcoord2f[0] = 0;
7197         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7198         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7199         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7200         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7201         r_bloomstate.bloomtexcoord2f[5] = 0;
7202         r_bloomstate.bloomtexcoord2f[6] = 0;
7203         r_bloomstate.bloomtexcoord2f[7] = 0;
7204
7205         if (r_hdr.integer || r_bloom.integer)
7206         {
7207                 r_bloomstate.enabled = true;
7208                 r_bloomstate.hdr = r_hdr.integer != 0;
7209         }
7210
7211         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);
7212 }
7213
7214 void R_Bloom_CopyBloomTexture(float colorscale)
7215 {
7216         r_refdef.stats.bloom++;
7217
7218         // scale down screen texture to the bloom texture size
7219         CHECKGLERROR
7220         R_SetViewport(&r_bloomstate.viewport);
7221         GL_BlendFunc(GL_ONE, GL_ZERO);
7222         GL_Color(colorscale, colorscale, colorscale, 1);
7223         // TODO: optimize with multitexture or GLSL
7224         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7225         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7226         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7227         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7228
7229         // we now have a bloom image in the framebuffer
7230         // copy it into the bloom image texture for later processing
7231         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);
7232         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7233 }
7234
7235 void R_Bloom_CopyHDRTexture(void)
7236 {
7237         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);
7238         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7239 }
7240
7241 void R_Bloom_MakeTexture(void)
7242 {
7243         int x, range, dir;
7244         float xoffset, yoffset, r, brighten;
7245
7246         r_refdef.stats.bloom++;
7247
7248         R_ResetViewRendering2D();
7249         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7250         R_Mesh_ColorPointer(NULL, 0, 0);
7251
7252         // we have a bloom image in the framebuffer
7253         CHECKGLERROR
7254         R_SetViewport(&r_bloomstate.viewport);
7255
7256         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7257         {
7258                 x *= 2;
7259                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7260                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7261                 GL_Color(r, r, r, 1);
7262                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7263                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7264                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7265                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7266
7267                 // copy the vertically blurred bloom view to a texture
7268                 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);
7269                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7270         }
7271
7272         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7273         brighten = r_bloom_brighten.value;
7274         if (r_hdr.integer)
7275                 brighten *= r_hdr_range.value;
7276         brighten = sqrt(brighten);
7277         if(range >= 1)
7278                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7279         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7280         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7281
7282         for (dir = 0;dir < 2;dir++)
7283         {
7284                 // blend on at multiple vertical offsets to achieve a vertical blur
7285                 // TODO: do offset blends using GLSL
7286                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7287                 GL_BlendFunc(GL_ONE, GL_ZERO);
7288                 for (x = -range;x <= range;x++)
7289                 {
7290                         if (!dir){xoffset = 0;yoffset = x;}
7291                         else {xoffset = x;yoffset = 0;}
7292                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7293                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7294                         // compute a texcoord array with the specified x and y offset
7295                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7296                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7297                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7298                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7299                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7300                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7301                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7302                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7303                         // this r value looks like a 'dot' particle, fading sharply to
7304                         // black at the edges
7305                         // (probably not realistic but looks good enough)
7306                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7307                         //r = brighten/(range*2+1);
7308                         r = brighten / (range * 2 + 1);
7309                         if(range >= 1)
7310                                 r *= (1 - x*x/(float)(range*range));
7311                         GL_Color(r, r, r, 1);
7312                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7313                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7314                         GL_BlendFunc(GL_ONE, GL_ONE);
7315                 }
7316
7317                 // copy the vertically blurred bloom view to a texture
7318                 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);
7319                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7320         }
7321
7322         // apply subtract last
7323         // (just like it would be in a GLSL shader)
7324         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7325         {
7326                 GL_BlendFunc(GL_ONE, GL_ZERO);
7327                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7328                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7329                 GL_Color(1, 1, 1, 1);
7330                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7331                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7332
7333                 GL_BlendFunc(GL_ONE, GL_ONE);
7334                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7335                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7336                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7337                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7338                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7339                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7340                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7341
7342                 // copy the darkened bloom view to a texture
7343                 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);
7344                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7345         }
7346 }
7347
7348 void R_HDR_RenderBloomTexture(void)
7349 {
7350         int oldwidth, oldheight;
7351         float oldcolorscale;
7352
7353         oldcolorscale = r_refdef.view.colorscale;
7354         oldwidth = r_refdef.view.width;
7355         oldheight = r_refdef.view.height;
7356         r_refdef.view.width = r_bloomstate.bloomwidth;
7357         r_refdef.view.height = r_bloomstate.bloomheight;
7358
7359         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7360         // TODO: add exposure compensation features
7361         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7362
7363         r_refdef.view.showdebug = false;
7364         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7365
7366         R_ResetViewRendering3D();
7367
7368         R_ClearScreen(r_refdef.fogenabled);
7369         if (r_timereport_active)
7370                 R_TimeReport("HDRclear");
7371
7372         R_View_Update();
7373         if (r_timereport_active)
7374                 R_TimeReport("visibility");
7375
7376         // only do secondary renders with HDR if r_hdr is 2 or higher
7377         r_waterstate.numwaterplanes = 0;
7378         if (r_waterstate.enabled && r_hdr.integer >= 2)
7379                 R_RenderWaterPlanes();
7380
7381         r_refdef.view.showdebug = true;
7382         R_RenderScene();
7383         r_waterstate.numwaterplanes = 0;
7384
7385         R_ResetViewRendering2D();
7386
7387         R_Bloom_CopyHDRTexture();
7388         R_Bloom_MakeTexture();
7389
7390         // restore the view settings
7391         r_refdef.view.width = oldwidth;
7392         r_refdef.view.height = oldheight;
7393         r_refdef.view.colorscale = oldcolorscale;
7394
7395         R_ResetViewRendering3D();
7396
7397         R_ClearScreen(r_refdef.fogenabled);
7398         if (r_timereport_active)
7399                 R_TimeReport("viewclear");
7400 }
7401
7402 static void R_BlendView(void)
7403 {
7404         unsigned int permutation;
7405         float uservecs[4][4];
7406
7407         switch (vid.renderpath)
7408         {
7409         case RENDERPATH_GL20:
7410         case RENDERPATH_CGGL:
7411                 permutation =
7412                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7413                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7414                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7415                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7416                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7417
7418                 if (r_bloomstate.texture_screen)
7419                 {
7420                         // make sure the buffer is available
7421                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7422
7423                         R_ResetViewRendering2D();
7424                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7425                         R_Mesh_ColorPointer(NULL, 0, 0);
7426
7427                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7428                         {
7429                                 // declare variables
7430                                 float speed;
7431                                 static float avgspeed;
7432
7433                                 speed = VectorLength(cl.movement_velocity);
7434
7435                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7436                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7437
7438                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7439                                 speed = bound(0, speed, 1);
7440                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7441
7442                                 // calculate values into a standard alpha
7443                                 cl.motionbluralpha = 1 - exp(-
7444                                                 (
7445                                                  (r_motionblur.value * speed / 80)
7446                                                  +
7447                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7448                                                 )
7449                                                 /
7450                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7451                                            );
7452
7453                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7454                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7455                                 // apply the blur
7456                                 if (cl.motionbluralpha > 0)
7457                                 {
7458                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7459                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7460                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7461                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7462                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7463                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7464                                 }
7465                         }
7466
7467                         // copy view into the screen texture
7468                         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);
7469                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7470                 }
7471                 else if (!r_bloomstate.texture_bloom)
7472                 {
7473                         // we may still have to do view tint...
7474                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7475                         {
7476                                 // apply a color tint to the whole view
7477                                 R_ResetViewRendering2D();
7478                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7479                                 R_Mesh_ColorPointer(NULL, 0, 0);
7480                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7481                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7482                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7483                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7484                         }
7485                         break; // no screen processing, no bloom, skip it
7486                 }
7487
7488                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7489                 {
7490                         // render simple bloom effect
7491                         // copy the screen and shrink it and darken it for the bloom process
7492                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7493                         // make the bloom texture
7494                         R_Bloom_MakeTexture();
7495                 }
7496
7497 #if _MSC_VER >= 1400
7498 #define sscanf sscanf_s
7499 #endif
7500                 memset(uservecs, 0, sizeof(uservecs));
7501                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7502                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7503                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7504                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7505
7506                 R_ResetViewRendering2D();
7507                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7508                 R_Mesh_ColorPointer(NULL, 0, 0);
7509                 GL_Color(1, 1, 1, 1);
7510                 GL_BlendFunc(GL_ONE, GL_ZERO);
7511                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7512                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7513
7514                 switch(vid.renderpath)
7515                 {
7516                 case RENDERPATH_GL20:
7517                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7518                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7519                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7520                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7521                         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]);
7522                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7523                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7524                         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]);
7525                         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]);
7526                         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]);
7527                         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]);
7528                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7529                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7530                         break;
7531                 case RENDERPATH_CGGL:
7532 #ifdef SUPPORTCG
7533                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7534                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7535                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7536                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7537                         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
7538                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7539                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7540                         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
7541                         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
7542                         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
7543                         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
7544                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7545                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7546 #endif
7547                         break;
7548                 default:
7549                         break;
7550                 }
7551                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7552                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7553                 break;
7554         case RENDERPATH_GL13:
7555         case RENDERPATH_GL11:
7556                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7557                 {
7558                         // apply a color tint to the whole view
7559                         R_ResetViewRendering2D();
7560                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7561                         R_Mesh_ColorPointer(NULL, 0, 0);
7562                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7563                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7564                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7565                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7566                 }
7567                 break;
7568         }
7569 }
7570
7571 matrix4x4_t r_waterscrollmatrix;
7572
7573 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7574 {
7575         if (r_refdef.fog_density)
7576         {
7577                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7578                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7579                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7580
7581                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7582                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7583                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7584                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7585
7586                 {
7587                         vec3_t fogvec;
7588                         VectorCopy(r_refdef.fogcolor, fogvec);
7589                         //   color.rgb *= ContrastBoost * SceneBrightness;
7590                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7591                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7592                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7593                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7594                 }
7595         }
7596 }
7597
7598 void R_UpdateVariables(void)
7599 {
7600         R_Textures_Frame();
7601
7602         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7603
7604         r_refdef.farclip = r_farclip_base.value;
7605         if (r_refdef.scene.worldmodel)
7606                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7607         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7608
7609         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7610                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7611         r_refdef.polygonfactor = 0;
7612         r_refdef.polygonoffset = 0;
7613         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7614         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7615
7616         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7617         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7618         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7619         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7620         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7621         if (r_showsurfaces.integer)
7622         {
7623                 r_refdef.scene.rtworld = false;
7624                 r_refdef.scene.rtworldshadows = false;
7625                 r_refdef.scene.rtdlight = false;
7626                 r_refdef.scene.rtdlightshadows = false;
7627                 r_refdef.lightmapintensity = 0;
7628         }
7629
7630         if (gamemode == GAME_NEHAHRA)
7631         {
7632                 if (gl_fogenable.integer)
7633                 {
7634                         r_refdef.oldgl_fogenable = true;
7635                         r_refdef.fog_density = gl_fogdensity.value;
7636                         r_refdef.fog_red = gl_fogred.value;
7637                         r_refdef.fog_green = gl_foggreen.value;
7638                         r_refdef.fog_blue = gl_fogblue.value;
7639                         r_refdef.fog_alpha = 1;
7640                         r_refdef.fog_start = 0;
7641                         r_refdef.fog_end = gl_skyclip.value;
7642                         r_refdef.fog_height = 1<<30;
7643                         r_refdef.fog_fadedepth = 128;
7644                 }
7645                 else if (r_refdef.oldgl_fogenable)
7646                 {
7647                         r_refdef.oldgl_fogenable = false;
7648                         r_refdef.fog_density = 0;
7649                         r_refdef.fog_red = 0;
7650                         r_refdef.fog_green = 0;
7651                         r_refdef.fog_blue = 0;
7652                         r_refdef.fog_alpha = 0;
7653                         r_refdef.fog_start = 0;
7654                         r_refdef.fog_end = 0;
7655                         r_refdef.fog_height = 1<<30;
7656                         r_refdef.fog_fadedepth = 128;
7657                 }
7658         }
7659
7660         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7661         r_refdef.fog_start = max(0, r_refdef.fog_start);
7662         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7663
7664         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7665
7666         if (r_refdef.fog_density && r_drawfog.integer)
7667         {
7668                 r_refdef.fogenabled = true;
7669                 // this is the point where the fog reaches 0.9986 alpha, which we
7670                 // consider a good enough cutoff point for the texture
7671                 // (0.9986 * 256 == 255.6)
7672                 if (r_fog_exp2.integer)
7673                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7674                 else
7675                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7676                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7677                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7678                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7679                 // fog color was already set
7680                 // update the fog texture
7681                 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)
7682                         R_BuildFogTexture();
7683         }
7684         else
7685                 r_refdef.fogenabled = false;
7686
7687         switch(vid.renderpath)
7688         {
7689         case RENDERPATH_GL20:
7690         case RENDERPATH_CGGL:
7691                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7692                 {
7693                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7694                         {
7695                                 // build GLSL gamma texture
7696 #define RAMPWIDTH 256
7697                                 unsigned short ramp[RAMPWIDTH * 3];
7698                                 unsigned char rampbgr[RAMPWIDTH][4];
7699                                 int i;
7700
7701                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7702
7703                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7704                                 for(i = 0; i < RAMPWIDTH; ++i)
7705                                 {
7706                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7707                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7708                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7709                                         rampbgr[i][3] = 0;
7710                                 }
7711                                 if (r_texture_gammaramps)
7712                                 {
7713                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7714                                 }
7715                                 else
7716                                 {
7717                                         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);
7718                                 }
7719                         }
7720                 }
7721                 else
7722                 {
7723                         // remove GLSL gamma texture
7724                 }
7725                 break;
7726         case RENDERPATH_GL13:
7727         case RENDERPATH_GL11:
7728                 break;
7729         }
7730 }
7731
7732 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7733 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7734 /*
7735 ================
7736 R_SelectScene
7737 ================
7738 */
7739 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7740         if( scenetype != r_currentscenetype ) {
7741                 // store the old scenetype
7742                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7743                 r_currentscenetype = scenetype;
7744                 // move in the new scene
7745                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7746         }
7747 }
7748
7749 /*
7750 ================
7751 R_GetScenePointer
7752 ================
7753 */
7754 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7755 {
7756         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7757         if( scenetype == r_currentscenetype ) {
7758                 return &r_refdef.scene;
7759         } else {
7760                 return &r_scenes_store[ scenetype ];
7761         }
7762 }
7763
7764 /*
7765 ================
7766 R_RenderView
7767 ================
7768 */
7769 void R_RenderView(void)
7770 {
7771         if (r_timereport_active)
7772                 R_TimeReport("start");
7773         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7774
7775         if (!r_drawentities.integer)
7776                 r_refdef.scene.numentities = 0;
7777
7778         R_AnimCache_ClearCache();
7779         R_FrameData_NewFrame();
7780
7781         if (r_refdef.view.isoverlay)
7782         {
7783                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7784                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7785                 R_TimeReport("depthclear");
7786
7787                 r_refdef.view.showdebug = false;
7788
7789                 r_waterstate.enabled = false;
7790                 r_waterstate.numwaterplanes = 0;
7791
7792                 R_RenderScene();
7793
7794                 CHECKGLERROR
7795                 return;
7796         }
7797
7798         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7799                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7800
7801         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7802
7803         // break apart the view matrix into vectors for various purposes
7804         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7805         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7806         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7807         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7808         // make an inverted copy of the view matrix for tracking sprites
7809         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7810
7811         R_Shadow_UpdateWorldLightSelection();
7812
7813         R_Bloom_StartFrame();
7814         R_Water_StartFrame();
7815
7816         CHECKGLERROR
7817         if (r_timereport_active)
7818                 R_TimeReport("viewsetup");
7819
7820         R_ResetViewRendering3D();
7821
7822         if (r_refdef.view.clear || r_refdef.fogenabled)
7823         {
7824                 R_ClearScreen(r_refdef.fogenabled);
7825                 if (r_timereport_active)
7826                         R_TimeReport("viewclear");
7827         }
7828         r_refdef.view.clear = true;
7829
7830         // this produces a bloom texture to be used in R_BlendView() later
7831         if (r_hdr.integer && r_bloomstate.bloomwidth)
7832                 R_HDR_RenderBloomTexture();
7833
7834         r_refdef.view.showdebug = true;
7835
7836         R_View_Update();
7837         if (r_timereport_active)
7838                 R_TimeReport("visibility");
7839
7840         r_waterstate.numwaterplanes = 0;
7841         if (r_waterstate.enabled)
7842                 R_RenderWaterPlanes();
7843
7844         R_RenderScene();
7845         r_waterstate.numwaterplanes = 0;
7846
7847         R_BlendView();
7848         if (r_timereport_active)
7849                 R_TimeReport("blendview");
7850
7851         GL_Scissor(0, 0, vid.width, vid.height);
7852         GL_ScissorTest(false);
7853         CHECKGLERROR
7854 }
7855
7856 void R_RenderWaterPlanes(void)
7857 {
7858         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7859         {
7860                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7861                 if (r_timereport_active)
7862                         R_TimeReport("waterworld");
7863         }
7864
7865         // don't let sound skip if going slow
7866         if (r_refdef.scene.extraupdate)
7867                 S_ExtraUpdate ();
7868
7869         R_DrawModelsAddWaterPlanes();
7870         if (r_timereport_active)
7871                 R_TimeReport("watermodels");
7872
7873         if (r_waterstate.numwaterplanes)
7874         {
7875                 R_Water_ProcessPlanes();
7876                 if (r_timereport_active)
7877                         R_TimeReport("waterscenes");
7878         }
7879 }
7880
7881 extern void R_DrawLightningBeams (void);
7882 extern void VM_CL_AddPolygonsToMeshQueue (void);
7883 extern void R_DrawPortals (void);
7884 extern cvar_t cl_locs_show;
7885 static void R_DrawLocs(void);
7886 static void R_DrawEntityBBoxes(void);
7887 static void R_DrawModelDecals(void);
7888 extern cvar_t cl_decals_newsystem;
7889 extern qboolean r_shadow_usingdeferredprepass;
7890 void R_RenderScene(void)
7891 {
7892         r_refdef.stats.renders++;
7893         r_textureframe++; // used only by R_GetCurrentTexture
7894
7895         R_UpdateFogColor();
7896
7897         // don't let sound skip if going slow
7898         if (r_refdef.scene.extraupdate)
7899                 S_ExtraUpdate ();
7900
7901         R_MeshQueue_BeginScene();
7902
7903         R_SkyStartFrame();
7904
7905         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);
7906
7907         if (cl.csqc_vidvars.drawworld)
7908         {
7909                 // don't let sound skip if going slow
7910                 if (r_refdef.scene.extraupdate)
7911                         S_ExtraUpdate ();
7912
7913                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7914                 {
7915                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7916                         if (r_timereport_active)
7917                                 R_TimeReport("worldsky");
7918                 }
7919
7920                 if (R_DrawBrushModelsSky() && r_timereport_active)
7921                         R_TimeReport("bmodelsky");
7922
7923                 if (skyrendermasked && skyrenderlater)
7924                 {
7925                         // we have to force off the water clipping plane while rendering sky
7926                         R_SetupView(false);
7927                         R_Sky();
7928                         R_SetupView(true);
7929                         if (r_timereport_active)
7930                                 R_TimeReport("sky");
7931                 }
7932         }
7933
7934         R_AnimCache_CacheVisibleEntities();
7935         if (r_timereport_active)
7936                 R_TimeReport("animation");
7937
7938         R_Shadow_PrepareLights();
7939         if (r_timereport_active)
7940                 R_TimeReport("preparelights");
7941
7942         if (r_shadow_usingdeferredprepass)
7943                 R_Shadow_DrawPrepass();
7944
7945         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7946         {
7947                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7948                 if (r_timereport_active)
7949                         R_TimeReport("worlddepth");
7950         }
7951         if (r_depthfirst.integer >= 2)
7952         {
7953                 R_DrawModelsDepth();
7954                 if (r_timereport_active)
7955                         R_TimeReport("modeldepth");
7956         }
7957
7958         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7959         {
7960                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7961                 if (r_timereport_active)
7962                         R_TimeReport("world");
7963         }
7964
7965         // don't let sound skip if going slow
7966         if (r_refdef.scene.extraupdate)
7967                 S_ExtraUpdate ();
7968
7969         R_DrawModels();
7970         if (r_timereport_active)
7971                 R_TimeReport("models");
7972
7973         // don't let sound skip if going slow
7974         if (r_refdef.scene.extraupdate)
7975                 S_ExtraUpdate ();
7976
7977         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7978         {
7979                 R_DrawModelShadows();
7980                 R_ResetViewRendering3D();
7981                 // don't let sound skip if going slow
7982                 if (r_refdef.scene.extraupdate)
7983                         S_ExtraUpdate ();
7984         }
7985
7986         if (!r_shadow_usingdeferredprepass)
7987         {
7988                 R_Shadow_DrawLights();
7989                 if (r_timereport_active)
7990                         R_TimeReport("rtlights");
7991         }
7992
7993         // don't let sound skip if going slow
7994         if (r_refdef.scene.extraupdate)
7995                 S_ExtraUpdate ();
7996
7997         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7998         {
7999                 R_DrawModelShadows();
8000                 R_ResetViewRendering3D();
8001                 // don't let sound skip if going slow
8002                 if (r_refdef.scene.extraupdate)
8003                         S_ExtraUpdate ();
8004         }
8005
8006         if (cl.csqc_vidvars.drawworld)
8007         {
8008                 if (cl_decals_newsystem.integer)
8009                 {
8010                         R_DrawModelDecals();
8011                         if (r_timereport_active)
8012                                 R_TimeReport("modeldecals");
8013                 }
8014                 else
8015                 {
8016                         R_DrawDecals();
8017                         if (r_timereport_active)
8018                                 R_TimeReport("decals");
8019                 }
8020
8021                 R_DrawParticles();
8022                 if (r_timereport_active)
8023                         R_TimeReport("particles");
8024
8025                 R_DrawExplosions();
8026                 if (r_timereport_active)
8027                         R_TimeReport("explosions");
8028
8029                 R_DrawLightningBeams();
8030                 if (r_timereport_active)
8031                         R_TimeReport("lightning");
8032         }
8033
8034         VM_CL_AddPolygonsToMeshQueue();
8035
8036         if (r_refdef.view.showdebug)
8037         {
8038                 if (cl_locs_show.integer)
8039                 {
8040                         R_DrawLocs();
8041                         if (r_timereport_active)
8042                                 R_TimeReport("showlocs");
8043                 }
8044
8045                 if (r_drawportals.integer)
8046                 {
8047                         R_DrawPortals();
8048                         if (r_timereport_active)
8049                                 R_TimeReport("portals");
8050                 }
8051
8052                 if (r_showbboxes.value > 0)
8053                 {
8054                         R_DrawEntityBBoxes();
8055                         if (r_timereport_active)
8056                                 R_TimeReport("bboxes");
8057                 }
8058         }
8059
8060         R_MeshQueue_RenderTransparent();
8061         if (r_timereport_active)
8062                 R_TimeReport("drawtrans");
8063
8064         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))
8065         {
8066                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8067                 if (r_timereport_active)
8068                         R_TimeReport("worlddebug");
8069                 R_DrawModelsDebug();
8070                 if (r_timereport_active)
8071                         R_TimeReport("modeldebug");
8072         }
8073
8074         if (cl.csqc_vidvars.drawworld)
8075         {
8076                 R_Shadow_DrawCoronas();
8077                 if (r_timereport_active)
8078                         R_TimeReport("coronas");
8079         }
8080
8081         // don't let sound skip if going slow
8082         if (r_refdef.scene.extraupdate)
8083                 S_ExtraUpdate ();
8084
8085         R_ResetViewRendering2D();
8086 }
8087
8088 static const unsigned short bboxelements[36] =
8089 {
8090         5, 1, 3, 5, 3, 7,
8091         6, 2, 0, 6, 0, 4,
8092         7, 3, 2, 7, 2, 6,
8093         4, 0, 1, 4, 1, 5,
8094         4, 5, 7, 4, 7, 6,
8095         1, 0, 2, 1, 2, 3,
8096 };
8097
8098 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8099 {
8100         int i;
8101         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8102
8103         RSurf_ActiveWorldEntity();
8104
8105         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8106         GL_DepthMask(false);
8107         GL_DepthRange(0, 1);
8108         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8109         R_Mesh_ResetTextureState();
8110
8111         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8112         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8113         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8114         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8115         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8116         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8117         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8118         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8119         R_FillColors(color4f, 8, cr, cg, cb, ca);
8120         if (r_refdef.fogenabled)
8121         {
8122                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8123                 {
8124                         f1 = RSurf_FogVertex(v);
8125                         f2 = 1 - f1;
8126                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8127                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8128                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8129                 }
8130         }
8131         R_Mesh_VertexPointer(vertex3f, 0, 0);
8132         R_Mesh_ColorPointer(color4f, 0, 0);
8133         R_Mesh_ResetTextureState();
8134         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8135         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8136 }
8137
8138 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8139 {
8140         int i;
8141         float color[4];
8142         prvm_edict_t *edict;
8143         prvm_prog_t *prog_save = prog;
8144
8145         // this function draws bounding boxes of server entities
8146         if (!sv.active)
8147                 return;
8148
8149         GL_CullFace(GL_NONE);
8150         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8151
8152         prog = 0;
8153         SV_VM_Begin();
8154         for (i = 0;i < numsurfaces;i++)
8155         {
8156                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8157                 switch ((int)edict->fields.server->solid)
8158                 {
8159                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8160                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8161                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8162                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8163                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8164                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8165                 }
8166                 color[3] *= r_showbboxes.value;
8167                 color[3] = bound(0, color[3], 1);
8168                 GL_DepthTest(!r_showdisabledepthtest.integer);
8169                 GL_CullFace(r_refdef.view.cullface_front);
8170                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8171         }
8172         SV_VM_End();
8173         prog = prog_save;
8174 }
8175
8176 static void R_DrawEntityBBoxes(void)
8177 {
8178         int i;
8179         prvm_edict_t *edict;
8180         vec3_t center;
8181         prvm_prog_t *prog_save = prog;
8182
8183         // this function draws bounding boxes of server entities
8184         if (!sv.active)
8185                 return;
8186
8187         prog = 0;
8188         SV_VM_Begin();
8189         for (i = 0;i < prog->num_edicts;i++)
8190         {
8191                 edict = PRVM_EDICT_NUM(i);
8192                 if (edict->priv.server->free)
8193                         continue;
8194                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8195                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8196                         continue;
8197                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8198                         continue;
8199                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8200                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8201         }
8202         SV_VM_End();
8203         prog = prog_save;
8204 }
8205
8206 static const int nomodelelement3i[24] =
8207 {
8208         5, 2, 0,
8209         5, 1, 2,
8210         5, 0, 3,
8211         5, 3, 1,
8212         0, 2, 4,
8213         2, 1, 4,
8214         3, 0, 4,
8215         1, 3, 4
8216 };
8217
8218 static const unsigned short nomodelelement3s[24] =
8219 {
8220         5, 2, 0,
8221         5, 1, 2,
8222         5, 0, 3,
8223         5, 3, 1,
8224         0, 2, 4,
8225         2, 1, 4,
8226         3, 0, 4,
8227         1, 3, 4
8228 };
8229
8230 static const float nomodelvertex3f[6*3] =
8231 {
8232         -16,   0,   0,
8233          16,   0,   0,
8234           0, -16,   0,
8235           0,  16,   0,
8236           0,   0, -16,
8237           0,   0,  16
8238 };
8239
8240 static const float nomodelcolor4f[6*4] =
8241 {
8242         0.0f, 0.0f, 0.5f, 1.0f,
8243         0.0f, 0.0f, 0.5f, 1.0f,
8244         0.0f, 0.5f, 0.0f, 1.0f,
8245         0.0f, 0.5f, 0.0f, 1.0f,
8246         0.5f, 0.0f, 0.0f, 1.0f,
8247         0.5f, 0.0f, 0.0f, 1.0f
8248 };
8249
8250 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8251 {
8252         int i;
8253         float f1, f2, *c;
8254         float color4f[6*4];
8255
8256         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);
8257
8258         // this is only called once per entity so numsurfaces is always 1, and
8259         // surfacelist is always {0}, so this code does not handle batches
8260
8261         if (rsurface.ent_flags & RENDER_ADDITIVE)
8262         {
8263                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8264                 GL_DepthMask(false);
8265         }
8266         else if (rsurface.colormod[3] < 1)
8267         {
8268                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8269                 GL_DepthMask(false);
8270         }
8271         else
8272         {
8273                 GL_BlendFunc(GL_ONE, GL_ZERO);
8274                 GL_DepthMask(true);
8275         }
8276         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8277         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8278         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8279         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8280         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8281         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8282         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8283         R_Mesh_ColorPointer(color4f, 0, 0);
8284         for (i = 0, c = color4f;i < 6;i++, c += 4)
8285         {
8286                 c[0] *= rsurface.colormod[0];
8287                 c[1] *= rsurface.colormod[1];
8288                 c[2] *= rsurface.colormod[2];
8289                 c[3] *= rsurface.colormod[3];
8290         }
8291         if (r_refdef.fogenabled)
8292         {
8293                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8294                 {
8295                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8296                         f2 = 1 - f1;
8297                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8298                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8299                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8300                 }
8301         }
8302         R_Mesh_ResetTextureState();
8303         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8304 }
8305
8306 void R_DrawNoModel(entity_render_t *ent)
8307 {
8308         vec3_t org;
8309         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8310         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8311                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8312         else
8313                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8314 }
8315
8316 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8317 {
8318         vec3_t right1, right2, diff, normal;
8319
8320         VectorSubtract (org2, org1, normal);
8321
8322         // calculate 'right' vector for start
8323         VectorSubtract (r_refdef.view.origin, org1, diff);
8324         CrossProduct (normal, diff, right1);
8325         VectorNormalize (right1);
8326
8327         // calculate 'right' vector for end
8328         VectorSubtract (r_refdef.view.origin, org2, diff);
8329         CrossProduct (normal, diff, right2);
8330         VectorNormalize (right2);
8331
8332         vert[ 0] = org1[0] + width * right1[0];
8333         vert[ 1] = org1[1] + width * right1[1];
8334         vert[ 2] = org1[2] + width * right1[2];
8335         vert[ 3] = org1[0] - width * right1[0];
8336         vert[ 4] = org1[1] - width * right1[1];
8337         vert[ 5] = org1[2] - width * right1[2];
8338         vert[ 6] = org2[0] - width * right2[0];
8339         vert[ 7] = org2[1] - width * right2[1];
8340         vert[ 8] = org2[2] - width * right2[2];
8341         vert[ 9] = org2[0] + width * right2[0];
8342         vert[10] = org2[1] + width * right2[1];
8343         vert[11] = org2[2] + width * right2[2];
8344 }
8345
8346 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)
8347 {
8348         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8349         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8350         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8351         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8352         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8353         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8354         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8355         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8356         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8357         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8358         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8359         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8360 }
8361
8362 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8363 {
8364         int i;
8365         float *vertex3f;
8366         float v[3];
8367         VectorSet(v, x, y, z);
8368         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8369                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8370                         break;
8371         if (i == mesh->numvertices)
8372         {
8373                 if (mesh->numvertices < mesh->maxvertices)
8374                 {
8375                         VectorCopy(v, vertex3f);
8376                         mesh->numvertices++;
8377                 }
8378                 return mesh->numvertices;
8379         }
8380         else
8381                 return i;
8382 }
8383
8384 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8385 {
8386         int i;
8387         int *e, element[3];
8388         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8389         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8390         e = mesh->element3i + mesh->numtriangles * 3;
8391         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8392         {
8393                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8394                 if (mesh->numtriangles < mesh->maxtriangles)
8395                 {
8396                         *e++ = element[0];
8397                         *e++ = element[1];
8398                         *e++ = element[2];
8399                         mesh->numtriangles++;
8400                 }
8401                 element[1] = element[2];
8402         }
8403 }
8404
8405 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8406 {
8407         int i;
8408         int *e, element[3];
8409         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8410         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8411         e = mesh->element3i + mesh->numtriangles * 3;
8412         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8413         {
8414                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8415                 if (mesh->numtriangles < mesh->maxtriangles)
8416                 {
8417                         *e++ = element[0];
8418                         *e++ = element[1];
8419                         *e++ = element[2];
8420                         mesh->numtriangles++;
8421                 }
8422                 element[1] = element[2];
8423         }
8424 }
8425
8426 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8427 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8428 {
8429         int planenum, planenum2;
8430         int w;
8431         int tempnumpoints;
8432         mplane_t *plane, *plane2;
8433         double maxdist;
8434         double temppoints[2][256*3];
8435         // figure out how large a bounding box we need to properly compute this brush
8436         maxdist = 0;
8437         for (w = 0;w < numplanes;w++)
8438                 maxdist = max(maxdist, fabs(planes[w].dist));
8439         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8440         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8441         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8442         {
8443                 w = 0;
8444                 tempnumpoints = 4;
8445                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8446                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8447                 {
8448                         if (planenum2 == planenum)
8449                                 continue;
8450                         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);
8451                         w = !w;
8452                 }
8453                 if (tempnumpoints < 3)
8454                         continue;
8455                 // generate elements forming a triangle fan for this polygon
8456                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8457         }
8458 }
8459
8460 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)
8461 {
8462         texturelayer_t *layer;
8463         layer = t->currentlayers + t->currentnumlayers++;
8464         layer->type = type;
8465         layer->depthmask = depthmask;
8466         layer->blendfunc1 = blendfunc1;
8467         layer->blendfunc2 = blendfunc2;
8468         layer->texture = texture;
8469         layer->texmatrix = *matrix;
8470         layer->color[0] = r;
8471         layer->color[1] = g;
8472         layer->color[2] = b;
8473         layer->color[3] = a;
8474 }
8475
8476 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8477 {
8478         double index, f;
8479         index = parms[2] + r_refdef.scene.time * parms[3];
8480         index -= floor(index);
8481         switch (func)
8482         {
8483         default:
8484         case Q3WAVEFUNC_NONE:
8485         case Q3WAVEFUNC_NOISE:
8486         case Q3WAVEFUNC_COUNT:
8487                 f = 0;
8488                 break;
8489         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8490         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8491         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8492         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8493         case Q3WAVEFUNC_TRIANGLE:
8494                 index *= 4;
8495                 f = index - floor(index);
8496                 if (index < 1)
8497                         f = f;
8498                 else if (index < 2)
8499                         f = 1 - f;
8500                 else if (index < 3)
8501                         f = -f;
8502                 else
8503                         f = -(1 - f);
8504                 break;
8505         }
8506         return (float)(parms[0] + parms[1] * f);
8507 }
8508
8509 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8510 {
8511         int w, h, idx;
8512         float f;
8513         float tcmat[12];
8514         matrix4x4_t matrix, temp;
8515         switch(tcmod->tcmod)
8516         {
8517                 case Q3TCMOD_COUNT:
8518                 case Q3TCMOD_NONE:
8519                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8520                                 matrix = r_waterscrollmatrix;
8521                         else
8522                                 matrix = identitymatrix;
8523                         break;
8524                 case Q3TCMOD_ENTITYTRANSLATE:
8525                         // this is used in Q3 to allow the gamecode to control texcoord
8526                         // scrolling on the entity, which is not supported in darkplaces yet.
8527                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8528                         break;
8529                 case Q3TCMOD_ROTATE:
8530                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8531                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8532                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8533                         break;
8534                 case Q3TCMOD_SCALE:
8535                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8536                         break;
8537                 case Q3TCMOD_SCROLL:
8538                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8539                         break;
8540                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8541                         w = (int) tcmod->parms[0];
8542                         h = (int) tcmod->parms[1];
8543                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8544                         f = f - floor(f);
8545                         idx = (int) floor(f * w * h);
8546                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8547                         break;
8548                 case Q3TCMOD_STRETCH:
8549                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8550                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8551                         break;
8552                 case Q3TCMOD_TRANSFORM:
8553                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8554                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8555                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8556                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8557                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8558                         break;
8559                 case Q3TCMOD_TURBULENT:
8560                         // this is handled in the RSurf_PrepareVertices function
8561                         matrix = identitymatrix;
8562                         break;
8563         }
8564         temp = *texmatrix;
8565         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8566 }
8567
8568 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8569 {
8570         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8571         char name[MAX_QPATH];
8572         skinframe_t *skinframe;
8573         unsigned char pixels[296*194];
8574         strlcpy(cache->name, skinname, sizeof(cache->name));
8575         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8576         if (developer_loading.integer)
8577                 Con_Printf("loading %s\n", name);
8578         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8579         if (!skinframe || !skinframe->base)
8580         {
8581                 unsigned char *f;
8582                 fs_offset_t filesize;
8583                 skinframe = NULL;
8584                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8585                 if (f)
8586                 {
8587                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8588                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8589                         Mem_Free(f);
8590                 }
8591         }
8592         cache->skinframe = skinframe;
8593 }
8594
8595 texture_t *R_GetCurrentTexture(texture_t *t)
8596 {
8597         int i;
8598         const entity_render_t *ent = rsurface.entity;
8599         dp_model_t *model = ent->model;
8600         q3shaderinfo_layer_tcmod_t *tcmod;
8601
8602         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8603                 return t->currentframe;
8604         t->update_lastrenderframe = r_textureframe;
8605         t->update_lastrenderentity = (void *)ent;
8606
8607         // switch to an alternate material if this is a q1bsp animated material
8608         {
8609                 texture_t *texture = t;
8610                 int s = rsurface.ent_skinnum;
8611                 if ((unsigned int)s >= (unsigned int)model->numskins)
8612                         s = 0;
8613                 if (model->skinscenes)
8614                 {
8615                         if (model->skinscenes[s].framecount > 1)
8616                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8617                         else
8618                                 s = model->skinscenes[s].firstframe;
8619                 }
8620                 if (s > 0)
8621                         t = t + s * model->num_surfaces;
8622                 if (t->animated)
8623                 {
8624                         // use an alternate animation if the entity's frame is not 0,
8625                         // and only if the texture has an alternate animation
8626                         if (rsurface.ent_alttextures && t->anim_total[1])
8627                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8628                         else
8629                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8630                 }
8631                 texture->currentframe = t;
8632         }
8633
8634         // update currentskinframe to be a qw skin or animation frame
8635         if (rsurface.ent_qwskin >= 0)
8636         {
8637                 i = rsurface.ent_qwskin;
8638                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8639                 {
8640                         r_qwskincache_size = cl.maxclients;
8641                         if (r_qwskincache)
8642                                 Mem_Free(r_qwskincache);
8643                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8644                 }
8645                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8646                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8647                 t->currentskinframe = r_qwskincache[i].skinframe;
8648                 if (t->currentskinframe == NULL)
8649                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8650         }
8651         else if (t->numskinframes >= 2)
8652                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8653         if (t->backgroundnumskinframes >= 2)
8654                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8655
8656         t->currentmaterialflags = t->basematerialflags;
8657         t->currentalpha = rsurface.colormod[3];
8658         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8659                 t->currentalpha *= r_wateralpha.value;
8660         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8661                 t->currentalpha *= t->r_water_wateralpha;
8662         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8663                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8664         if (!(rsurface.ent_flags & RENDER_LIGHT))
8665                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8666         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8667         {
8668                 // pick a model lighting mode
8669                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8670                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8671                 else
8672                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8673         }
8674         if (rsurface.ent_flags & RENDER_ADDITIVE)
8675                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8676         else if (t->currentalpha < 1)
8677                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8678         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8679                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8680         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8681                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8682         if (t->backgroundnumskinframes)
8683                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8684         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8685         {
8686                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8687                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8688         }
8689         else
8690                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8691         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8692                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8693
8694         // there is no tcmod
8695         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8696         {
8697                 t->currenttexmatrix = r_waterscrollmatrix;
8698                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8699         }
8700         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8701         {
8702                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8703                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8704         }
8705
8706         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8707                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8708         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8709                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8710
8711         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8712         if (t->currentskinframe->qpixels)
8713                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8714         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8715         if (!t->basetexture)
8716                 t->basetexture = r_texture_notexture;
8717         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8718         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8719         t->nmaptexture = t->currentskinframe->nmap;
8720         if (!t->nmaptexture)
8721                 t->nmaptexture = r_texture_blanknormalmap;
8722         t->glosstexture = r_texture_black;
8723         t->glowtexture = t->currentskinframe->glow;
8724         t->fogtexture = t->currentskinframe->fog;
8725         if (t->backgroundnumskinframes)
8726         {
8727                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8728                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8729                 t->backgroundglosstexture = r_texture_black;
8730                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8731                 if (!t->backgroundnmaptexture)
8732                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8733         }
8734         else
8735         {
8736                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8737                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8738                 t->backgroundglosstexture = r_texture_black;
8739                 t->backgroundglowtexture = NULL;
8740         }
8741         t->specularpower = r_shadow_glossexponent.value;
8742         // TODO: store reference values for these in the texture?
8743         t->specularscale = 0;
8744         if (r_shadow_gloss.integer > 0)
8745         {
8746                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8747                 {
8748                         if (r_shadow_glossintensity.value > 0)
8749                         {
8750                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8751                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8752                                 t->specularscale = r_shadow_glossintensity.value;
8753                         }
8754                 }
8755                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8756                 {
8757                         t->glosstexture = r_texture_white;
8758                         t->backgroundglosstexture = r_texture_white;
8759                         t->specularscale = r_shadow_gloss2intensity.value;
8760                         t->specularpower = r_shadow_gloss2exponent.value;
8761                 }
8762         }
8763         t->specularscale *= t->specularscalemod;
8764         t->specularpower *= t->specularpowermod;
8765
8766         // lightmaps mode looks bad with dlights using actual texturing, so turn
8767         // off the colormap and glossmap, but leave the normalmap on as it still
8768         // accurately represents the shading involved
8769         if (gl_lightmaps.integer)
8770         {
8771                 t->basetexture = r_texture_grey128;
8772                 t->pantstexture = r_texture_black;
8773                 t->shirttexture = r_texture_black;
8774                 t->nmaptexture = r_texture_blanknormalmap;
8775                 t->glosstexture = r_texture_black;
8776                 t->glowtexture = NULL;
8777                 t->fogtexture = NULL;
8778                 t->backgroundbasetexture = NULL;
8779                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8780                 t->backgroundglosstexture = r_texture_black;
8781                 t->backgroundglowtexture = NULL;
8782                 t->specularscale = 0;
8783                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8784         }
8785
8786         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8787         VectorClear(t->dlightcolor);
8788         t->currentnumlayers = 0;
8789         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8790         {
8791                 int blendfunc1, blendfunc2;
8792                 qboolean depthmask;
8793                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8794                 {
8795                         blendfunc1 = GL_SRC_ALPHA;
8796                         blendfunc2 = GL_ONE;
8797                 }
8798                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8799                 {
8800                         blendfunc1 = GL_SRC_ALPHA;
8801                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8802                 }
8803                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8804                 {
8805                         blendfunc1 = t->customblendfunc[0];
8806                         blendfunc2 = t->customblendfunc[1];
8807                 }
8808                 else
8809                 {
8810                         blendfunc1 = GL_ONE;
8811                         blendfunc2 = GL_ZERO;
8812                 }
8813                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8814                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8815                 {
8816                         // fullbright is not affected by r_refdef.lightmapintensity
8817                         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]);
8818                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8819                                 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]);
8820                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8821                                 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]);
8822                 }
8823                 else
8824                 {
8825                         vec3_t ambientcolor;
8826                         float colorscale;
8827                         // set the color tint used for lights affecting this surface
8828                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8829                         colorscale = 2;
8830                         // q3bsp has no lightmap updates, so the lightstylevalue that
8831                         // would normally be baked into the lightmap must be
8832                         // applied to the color
8833                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8834                         if (model->type == mod_brushq3)
8835                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8836                         colorscale *= r_refdef.lightmapintensity;
8837                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8838                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8839                         // basic lit geometry
8840                         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]);
8841                         // add pants/shirt if needed
8842                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8843                                 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]);
8844                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8845                                 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]);
8846                         // now add ambient passes if needed
8847                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8848                         {
8849                                 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]);
8850                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8851                                         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]);
8852                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8853                                         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]);
8854                         }
8855                 }
8856                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8857                         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]);
8858                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8859                 {
8860                         // if this is opaque use alpha blend which will darken the earlier
8861                         // passes cheaply.
8862                         //
8863                         // if this is an alpha blended material, all the earlier passes
8864                         // were darkened by fog already, so we only need to add the fog
8865                         // color ontop through the fog mask texture
8866                         //
8867                         // if this is an additive blended material, all the earlier passes
8868                         // were darkened by fog already, and we should not add fog color
8869                         // (because the background was not darkened, there is no fog color
8870                         // that was lost behind it).
8871                         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]);
8872                 }
8873         }
8874
8875         return t->currentframe;
8876 }
8877
8878 rsurfacestate_t rsurface;
8879
8880 void R_Mesh_ResizeArrays(int newvertices)
8881 {
8882         float *base;
8883         if (rsurface.array_size >= newvertices)
8884                 return;
8885         if (rsurface.array_modelvertex3f)
8886                 Mem_Free(rsurface.array_modelvertex3f);
8887         rsurface.array_size = (newvertices + 1023) & ~1023;
8888         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8889         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8890         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8891         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8892         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8893         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8894         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8895         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8896         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8897         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8898         rsurface.array_color4f           = base + rsurface.array_size * 27;
8899         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8900 }
8901
8902 void RSurf_ActiveWorldEntity(void)
8903 {
8904         dp_model_t *model = r_refdef.scene.worldmodel;
8905         //if (rsurface.entity == r_refdef.scene.worldentity)
8906         //      return;
8907         rsurface.entity = r_refdef.scene.worldentity;
8908         rsurface.skeleton = NULL;
8909         rsurface.ent_skinnum = 0;
8910         rsurface.ent_qwskin = -1;
8911         rsurface.ent_shadertime = 0;
8912         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8913         if (rsurface.array_size < model->surfmesh.num_vertices)
8914                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8915         rsurface.matrix = identitymatrix;
8916         rsurface.inversematrix = identitymatrix;
8917         rsurface.matrixscale = 1;
8918         rsurface.inversematrixscale = 1;
8919         R_EntityMatrix(&identitymatrix);
8920         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8921         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8922         rsurface.fograngerecip = r_refdef.fograngerecip;
8923         rsurface.fogheightfade = r_refdef.fogheightfade;
8924         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8925         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8926         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8927         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8928         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8929         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8930         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8931         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8932         rsurface.colormod[3] = 1;
8933         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);
8934         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8935         rsurface.frameblend[0].lerp = 1;
8936         rsurface.ent_alttextures = false;
8937         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8938         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8939         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8940         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8941         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8942         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8943         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8944         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8945         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8946         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8947         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8948         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8949         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8950         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8951         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8952         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8953         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8954         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8955         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8956         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8957         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8958         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8959         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8960         rsurface.modelelement3i = model->surfmesh.data_element3i;
8961         rsurface.modelelement3s = model->surfmesh.data_element3s;
8962         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8963         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8964         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8965         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8966         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8967         rsurface.modelsurfaces = model->data_surfaces;
8968         rsurface.generatedvertex = false;
8969         rsurface.vertex3f  = rsurface.modelvertex3f;
8970         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8971         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8972         rsurface.svector3f = rsurface.modelsvector3f;
8973         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8974         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8975         rsurface.tvector3f = rsurface.modeltvector3f;
8976         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8977         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8978         rsurface.normal3f  = rsurface.modelnormal3f;
8979         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8980         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8981         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8982 }
8983
8984 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8985 {
8986         dp_model_t *model = ent->model;
8987         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8988         //      return;
8989         rsurface.entity = (entity_render_t *)ent;
8990         rsurface.skeleton = ent->skeleton;
8991         rsurface.ent_skinnum = ent->skinnum;
8992         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;
8993         rsurface.ent_shadertime = ent->shadertime;
8994         rsurface.ent_flags = ent->flags;
8995         if (rsurface.array_size < model->surfmesh.num_vertices)
8996                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8997         rsurface.matrix = ent->matrix;
8998         rsurface.inversematrix = ent->inversematrix;
8999         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9000         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9001         R_EntityMatrix(&rsurface.matrix);
9002         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9003         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9004         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9005         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9006         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9007         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9008         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9009         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9010         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9011         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9012         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9013         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9014         rsurface.colormod[3] = ent->alpha;
9015         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9016         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9017         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9018         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9019         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9020         if (ent->model->brush.submodel && !prepass)
9021         {
9022                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9023                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9024         }
9025         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9026         {
9027                 if (ent->animcache_vertex3f && !r_framedata_failed)
9028                 {
9029                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9030                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9031                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9032                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9033                 }
9034                 else if (wanttangents)
9035                 {
9036                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9037                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9038                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9039                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9040                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9041                 }
9042                 else if (wantnormals)
9043                 {
9044                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9045                         rsurface.modelsvector3f = NULL;
9046                         rsurface.modeltvector3f = NULL;
9047                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9048                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9049                 }
9050                 else
9051                 {
9052                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9053                         rsurface.modelsvector3f = NULL;
9054                         rsurface.modeltvector3f = NULL;
9055                         rsurface.modelnormal3f = NULL;
9056                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9057                 }
9058                 rsurface.modelvertex3f_bufferobject = 0;
9059                 rsurface.modelvertex3f_bufferoffset = 0;
9060                 rsurface.modelsvector3f_bufferobject = 0;
9061                 rsurface.modelsvector3f_bufferoffset = 0;
9062                 rsurface.modeltvector3f_bufferobject = 0;
9063                 rsurface.modeltvector3f_bufferoffset = 0;
9064                 rsurface.modelnormal3f_bufferobject = 0;
9065                 rsurface.modelnormal3f_bufferoffset = 0;
9066                 rsurface.generatedvertex = true;
9067         }
9068         else
9069         {
9070                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9071                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9072                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9073                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9074                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9075                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9076                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9077                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9078                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9079                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9080                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9081                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9082                 rsurface.generatedvertex = false;
9083         }
9084         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9085         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9086         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9087         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9088         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9089         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9090         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9091         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9092         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9093         rsurface.modelelement3i = model->surfmesh.data_element3i;
9094         rsurface.modelelement3s = model->surfmesh.data_element3s;
9095         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9096         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9097         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9098         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9099         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9100         rsurface.modelsurfaces = model->data_surfaces;
9101         rsurface.vertex3f  = rsurface.modelvertex3f;
9102         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9103         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9104         rsurface.svector3f = rsurface.modelsvector3f;
9105         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9106         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9107         rsurface.tvector3f = rsurface.modeltvector3f;
9108         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9109         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9110         rsurface.normal3f  = rsurface.modelnormal3f;
9111         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9112         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9113         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9114 }
9115
9116 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)
9117 {
9118         rsurface.entity = r_refdef.scene.worldentity;
9119         rsurface.skeleton = NULL;
9120         rsurface.ent_skinnum = 0;
9121         rsurface.ent_qwskin = -1;
9122         rsurface.ent_shadertime = shadertime;
9123         rsurface.ent_flags = entflags;
9124         rsurface.modelnum_vertices = numvertices;
9125         rsurface.modelnum_triangles = numtriangles;
9126         if (rsurface.array_size < rsurface.modelnum_vertices)
9127                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9128         rsurface.matrix = *matrix;
9129         rsurface.inversematrix = *inversematrix;
9130         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9131         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9132         R_EntityMatrix(&rsurface.matrix);
9133         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9134         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9135         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9136         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9137         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9138         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9139         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9140         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9141         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9142         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9143         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9144         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9145         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);
9146         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9147         rsurface.frameblend[0].lerp = 1;
9148         rsurface.ent_alttextures = false;
9149         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9150         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9151         if (wanttangents)
9152         {
9153                 rsurface.modelvertex3f = vertex3f;
9154                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9155                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9156                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9157         }
9158         else if (wantnormals)
9159         {
9160                 rsurface.modelvertex3f = vertex3f;
9161                 rsurface.modelsvector3f = NULL;
9162                 rsurface.modeltvector3f = NULL;
9163                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9164         }
9165         else
9166         {
9167                 rsurface.modelvertex3f = vertex3f;
9168                 rsurface.modelsvector3f = NULL;
9169                 rsurface.modeltvector3f = NULL;
9170                 rsurface.modelnormal3f = NULL;
9171         }
9172         rsurface.modelvertex3f_bufferobject = 0;
9173         rsurface.modelvertex3f_bufferoffset = 0;
9174         rsurface.modelsvector3f_bufferobject = 0;
9175         rsurface.modelsvector3f_bufferoffset = 0;
9176         rsurface.modeltvector3f_bufferobject = 0;
9177         rsurface.modeltvector3f_bufferoffset = 0;
9178         rsurface.modelnormal3f_bufferobject = 0;
9179         rsurface.modelnormal3f_bufferoffset = 0;
9180         rsurface.generatedvertex = true;
9181         rsurface.modellightmapcolor4f  = color4f;
9182         rsurface.modellightmapcolor4f_bufferobject = 0;
9183         rsurface.modellightmapcolor4f_bufferoffset = 0;
9184         rsurface.modeltexcoordtexture2f  = texcoord2f;
9185         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9186         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9187         rsurface.modeltexcoordlightmap2f  = NULL;
9188         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9189         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9190         rsurface.modelelement3i = element3i;
9191         rsurface.modelelement3s = element3s;
9192         rsurface.modelelement3i_bufferobject = 0;
9193         rsurface.modelelement3s_bufferobject = 0;
9194         rsurface.modellightmapoffsets = NULL;
9195         rsurface.modelsurfaces = NULL;
9196         rsurface.vertex3f  = rsurface.modelvertex3f;
9197         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9198         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9199         rsurface.svector3f = rsurface.modelsvector3f;
9200         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9201         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9202         rsurface.tvector3f = rsurface.modeltvector3f;
9203         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9204         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9205         rsurface.normal3f  = rsurface.modelnormal3f;
9206         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9207         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9208         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9209
9210         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9211         {
9212                 if ((wantnormals || wanttangents) && !normal3f)
9213                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9214                 if (wanttangents && !svector3f)
9215                         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);
9216         }
9217 }
9218
9219 float RSurf_FogPoint(const float *v)
9220 {
9221         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9222         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9223         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9224         float FogHeightFade = r_refdef.fogheightfade;
9225         float fogfrac;
9226         unsigned int fogmasktableindex;
9227         if (r_refdef.fogplaneviewabove)
9228                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9229         else
9230                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9231         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9232         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9233 }
9234
9235 float RSurf_FogVertex(const float *v)
9236 {
9237         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9238         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9239         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9240         float FogHeightFade = rsurface.fogheightfade;
9241         float fogfrac;
9242         unsigned int fogmasktableindex;
9243         if (r_refdef.fogplaneviewabove)
9244                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9245         else
9246                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9247         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9248         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9249 }
9250
9251 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9252 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9253 {
9254         int deformindex;
9255         int texturesurfaceindex;
9256         int i, j;
9257         float amplitude;
9258         float animpos;
9259         float scale;
9260         const float *v1, *in_tc;
9261         float *out_tc;
9262         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9263         float waveparms[4];
9264         q3shaderinfo_deform_t *deform;
9265         // 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
9266         if (rsurface.generatedvertex)
9267         {
9268                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9269                         generatenormals = true;
9270                 for (i = 0;i < Q3MAXDEFORMS;i++)
9271                 {
9272                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9273                         {
9274                                 generatetangents = true;
9275                                 generatenormals = true;
9276                         }
9277                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9278                                 generatenormals = true;
9279                 }
9280                 if (generatenormals && !rsurface.modelnormal3f)
9281                 {
9282                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9283                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9284                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9285                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9286                 }
9287                 if (generatetangents && !rsurface.modelsvector3f)
9288                 {
9289                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9290                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9291                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9292                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9293                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9294                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9295                         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);
9296                 }
9297         }
9298         rsurface.vertex3f  = rsurface.modelvertex3f;
9299         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9300         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9301         rsurface.svector3f = rsurface.modelsvector3f;
9302         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9303         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9304         rsurface.tvector3f = rsurface.modeltvector3f;
9305         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9306         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9307         rsurface.normal3f  = rsurface.modelnormal3f;
9308         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9309         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9310         // if vertices are deformed (sprite flares and things in maps, possibly
9311         // water waves, bulges and other deformations), generate them into
9312         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9313         // (may be static model data or generated data for an animated model, or
9314         //  the previous deform pass)
9315         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9316         {
9317                 switch (deform->deform)
9318                 {
9319                 default:
9320                 case Q3DEFORM_PROJECTIONSHADOW:
9321                 case Q3DEFORM_TEXT0:
9322                 case Q3DEFORM_TEXT1:
9323                 case Q3DEFORM_TEXT2:
9324                 case Q3DEFORM_TEXT3:
9325                 case Q3DEFORM_TEXT4:
9326                 case Q3DEFORM_TEXT5:
9327                 case Q3DEFORM_TEXT6:
9328                 case Q3DEFORM_TEXT7:
9329                 case Q3DEFORM_NONE:
9330                         break;
9331                 case Q3DEFORM_AUTOSPRITE:
9332                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9333                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9334                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9335                         VectorNormalize(newforward);
9336                         VectorNormalize(newright);
9337                         VectorNormalize(newup);
9338                         // make deformed versions of only the model vertices used by the specified surfaces
9339                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9340                         {
9341                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9342                                 // a single autosprite surface can contain multiple sprites...
9343                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9344                                 {
9345                                         VectorClear(center);
9346                                         for (i = 0;i < 4;i++)
9347                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9348                                         VectorScale(center, 0.25f, center);
9349                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9350                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9351                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9352                                         for (i = 0;i < 4;i++)
9353                                         {
9354                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9355                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9356                                         }
9357                                 }
9358                                 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);
9359                                 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);
9360                         }
9361                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9362                         rsurface.vertex3f_bufferobject = 0;
9363                         rsurface.vertex3f_bufferoffset = 0;
9364                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9365                         rsurface.svector3f_bufferobject = 0;
9366                         rsurface.svector3f_bufferoffset = 0;
9367                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9368                         rsurface.tvector3f_bufferobject = 0;
9369                         rsurface.tvector3f_bufferoffset = 0;
9370                         rsurface.normal3f = rsurface.array_deformednormal3f;
9371                         rsurface.normal3f_bufferobject = 0;
9372                         rsurface.normal3f_bufferoffset = 0;
9373                         break;
9374                 case Q3DEFORM_AUTOSPRITE2:
9375                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9376                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9377                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9378                         VectorNormalize(newforward);
9379                         VectorNormalize(newright);
9380                         VectorNormalize(newup);
9381                         // make deformed versions of only the model vertices used by the specified surfaces
9382                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9383                         {
9384                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9385                                 const float *v1, *v2;
9386                                 vec3_t start, end;
9387                                 float f, l;
9388                                 struct
9389                                 {
9390                                         float length2;
9391                                         const float *v1;
9392                                         const float *v2;
9393                                 }
9394                                 shortest[2];
9395                                 memset(shortest, 0, sizeof(shortest));
9396                                 // a single autosprite surface can contain multiple sprites...
9397                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9398                                 {
9399                                         VectorClear(center);
9400                                         for (i = 0;i < 4;i++)
9401                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9402                                         VectorScale(center, 0.25f, center);
9403                                         // find the two shortest edges, then use them to define the
9404                                         // axis vectors for rotating around the central axis
9405                                         for (i = 0;i < 6;i++)
9406                                         {
9407                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9408                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9409 #if 0
9410                                                 Debug_PolygonBegin(NULL, 0);
9411                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9412                                                 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);
9413                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9414                                                 Debug_PolygonEnd();
9415 #endif
9416                                                 l = VectorDistance2(v1, v2);
9417                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9418                                                 if (v1[2] != v2[2])
9419                                                         l += (1.0f / 1024.0f);
9420                                                 if (shortest[0].length2 > l || i == 0)
9421                                                 {
9422                                                         shortest[1] = shortest[0];
9423                                                         shortest[0].length2 = l;
9424                                                         shortest[0].v1 = v1;
9425                                                         shortest[0].v2 = v2;
9426                                                 }
9427                                                 else if (shortest[1].length2 > l || i == 1)
9428                                                 {
9429                                                         shortest[1].length2 = l;
9430                                                         shortest[1].v1 = v1;
9431                                                         shortest[1].v2 = v2;
9432                                                 }
9433                                         }
9434                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9435                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9436 #if 0
9437                                         Debug_PolygonBegin(NULL, 0);
9438                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9439                                         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);
9440                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9441                                         Debug_PolygonEnd();
9442 #endif
9443                                         // this calculates the right vector from the shortest edge
9444                                         // and the up vector from the edge midpoints
9445                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9446                                         VectorNormalize(right);
9447                                         VectorSubtract(end, start, up);
9448                                         VectorNormalize(up);
9449                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9450                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9451                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9452                                         VectorNegate(forward, forward);
9453                                         VectorReflect(forward, 0, up, forward);
9454                                         VectorNormalize(forward);
9455                                         CrossProduct(up, forward, newright);
9456                                         VectorNormalize(newright);
9457 #if 0
9458                                         Debug_PolygonBegin(NULL, 0);
9459                                         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);
9460                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9461                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9462                                         Debug_PolygonEnd();
9463 #endif
9464 #if 0
9465                                         Debug_PolygonBegin(NULL, 0);
9466                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9467                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9468                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9469                                         Debug_PolygonEnd();
9470 #endif
9471                                         // rotate the quad around the up axis vector, this is made
9472                                         // especially easy by the fact we know the quad is flat,
9473                                         // so we only have to subtract the center position and
9474                                         // measure distance along the right vector, and then
9475                                         // multiply that by the newright vector and add back the
9476                                         // center position
9477                                         // we also need to subtract the old position to undo the
9478                                         // displacement from the center, which we do with a
9479                                         // DotProduct, the subtraction/addition of center is also
9480                                         // optimized into DotProducts here
9481                                         l = DotProduct(right, center);
9482                                         for (i = 0;i < 4;i++)
9483                                         {
9484                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9485                                                 f = DotProduct(right, v1) - l;
9486                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9487                                         }
9488                                 }
9489                                 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);
9490                                 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);
9491                         }
9492                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9493                         rsurface.vertex3f_bufferobject = 0;
9494                         rsurface.vertex3f_bufferoffset = 0;
9495                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9496                         rsurface.svector3f_bufferobject = 0;
9497                         rsurface.svector3f_bufferoffset = 0;
9498                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9499                         rsurface.tvector3f_bufferobject = 0;
9500                         rsurface.tvector3f_bufferoffset = 0;
9501                         rsurface.normal3f = rsurface.array_deformednormal3f;
9502                         rsurface.normal3f_bufferobject = 0;
9503                         rsurface.normal3f_bufferoffset = 0;
9504                         break;
9505                 case Q3DEFORM_NORMAL:
9506                         // deform the normals to make reflections wavey
9507                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9508                         {
9509                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9510                                 for (j = 0;j < surface->num_vertices;j++)
9511                                 {
9512                                         float vertex[3];
9513                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9514                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9515                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9516                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9517                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9518                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9519                                         VectorNormalize(normal);
9520                                 }
9521                                 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);
9522                         }
9523                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9524                         rsurface.svector3f_bufferobject = 0;
9525                         rsurface.svector3f_bufferoffset = 0;
9526                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9527                         rsurface.tvector3f_bufferobject = 0;
9528                         rsurface.tvector3f_bufferoffset = 0;
9529                         rsurface.normal3f = rsurface.array_deformednormal3f;
9530                         rsurface.normal3f_bufferobject = 0;
9531                         rsurface.normal3f_bufferoffset = 0;
9532                         break;
9533                 case Q3DEFORM_WAVE:
9534                         // deform vertex array to make wavey water and flags and such
9535                         waveparms[0] = deform->waveparms[0];
9536                         waveparms[1] = deform->waveparms[1];
9537                         waveparms[2] = deform->waveparms[2];
9538                         waveparms[3] = deform->waveparms[3];
9539                         // this is how a divisor of vertex influence on deformation
9540                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9541                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9542                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9543                         {
9544                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9545                                 for (j = 0;j < surface->num_vertices;j++)
9546                                 {
9547                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9548                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9549                                         // if the wavefunc depends on time, evaluate it per-vertex
9550                                         if (waveparms[3])
9551                                         {
9552                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9553                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9554                                         }
9555                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9556                                 }
9557                         }
9558                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9559                         rsurface.vertex3f_bufferobject = 0;
9560                         rsurface.vertex3f_bufferoffset = 0;
9561                         break;
9562                 case Q3DEFORM_BULGE:
9563                         // deform vertex array to make the surface have moving bulges
9564                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9565                         {
9566                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9567                                 for (j = 0;j < surface->num_vertices;j++)
9568                                 {
9569                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9570                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9571                                 }
9572                         }
9573                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9574                         rsurface.vertex3f_bufferobject = 0;
9575                         rsurface.vertex3f_bufferoffset = 0;
9576                         break;
9577                 case Q3DEFORM_MOVE:
9578                         // deform vertex array
9579                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9580                         VectorScale(deform->parms, scale, waveparms);
9581                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9582                         {
9583                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9584                                 for (j = 0;j < surface->num_vertices;j++)
9585                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9586                         }
9587                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9588                         rsurface.vertex3f_bufferobject = 0;
9589                         rsurface.vertex3f_bufferoffset = 0;
9590                         break;
9591                 }
9592         }
9593         // generate texcoords based on the chosen texcoord source
9594         switch(rsurface.texture->tcgen.tcgen)
9595         {
9596         default:
9597         case Q3TCGEN_TEXTURE:
9598                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9599                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9600                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9601                 break;
9602         case Q3TCGEN_LIGHTMAP:
9603                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9604                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9605                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9606                 break;
9607         case Q3TCGEN_VECTOR:
9608                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9609                 {
9610                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9611                         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)
9612                         {
9613                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9614                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9615                         }
9616                 }
9617                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9618                 rsurface.texcoordtexture2f_bufferobject  = 0;
9619                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9620                 break;
9621         case Q3TCGEN_ENVIRONMENT:
9622                 // make environment reflections using a spheremap
9623                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9624                 {
9625                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9626                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9627                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9628                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9629                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9630                         {
9631                                 // identical to Q3A's method, but executed in worldspace so
9632                                 // carried models can be shiny too
9633
9634                                 float viewer[3], d, reflected[3], worldreflected[3];
9635
9636                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9637                                 // VectorNormalize(viewer);
9638
9639                                 d = DotProduct(normal, viewer);
9640
9641                                 reflected[0] = normal[0]*2*d - viewer[0];
9642                                 reflected[1] = normal[1]*2*d - viewer[1];
9643                                 reflected[2] = normal[2]*2*d - viewer[2];
9644                                 // note: this is proportinal to viewer, so we can normalize later
9645
9646                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9647                                 VectorNormalize(worldreflected);
9648
9649                                 // note: this sphere map only uses world x and z!
9650                                 // so positive and negative y will LOOK THE SAME.
9651                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9652                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9653                         }
9654                 }
9655                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9656                 rsurface.texcoordtexture2f_bufferobject  = 0;
9657                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9658                 break;
9659         }
9660         // the only tcmod that needs software vertex processing is turbulent, so
9661         // check for it here and apply the changes if needed
9662         // and we only support that as the first one
9663         // (handling a mixture of turbulent and other tcmods would be problematic
9664         //  without punting it entirely to a software path)
9665         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9666         {
9667                 amplitude = rsurface.texture->tcmods[0].parms[1];
9668                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9669                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9670                 {
9671                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9672                         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)
9673                         {
9674                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9675                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9676                         }
9677                 }
9678                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9679                 rsurface.texcoordtexture2f_bufferobject  = 0;
9680                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9681         }
9682         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9683         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9684         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9685         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9686 }
9687
9688 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9689 {
9690         int i, j;
9691         const msurface_t *surface = texturesurfacelist[0];
9692         const msurface_t *surface2;
9693         int firstvertex;
9694         int endvertex;
9695         int numvertices;
9696         int numtriangles;
9697         // TODO: lock all array ranges before render, rather than on each surface
9698         if (texturenumsurfaces == 1)
9699                 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);
9700         else if (r_batchmode.integer == 2)
9701         {
9702                 #define MAXBATCHTRIANGLES 4096
9703                 int batchtriangles = 0;
9704                 static int batchelements[MAXBATCHTRIANGLES*3];
9705                 for (i = 0;i < texturenumsurfaces;i = j)
9706                 {
9707                         surface = texturesurfacelist[i];
9708                         j = i + 1;
9709                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9710                         {
9711                                 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);
9712                                 continue;
9713                         }
9714                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9715                         batchtriangles = surface->num_triangles;
9716                         firstvertex = surface->num_firstvertex;
9717                         endvertex = surface->num_firstvertex + surface->num_vertices;
9718                         for (;j < texturenumsurfaces;j++)
9719                         {
9720                                 surface2 = texturesurfacelist[j];
9721                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9722                                         break;
9723                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9724                                 batchtriangles += surface2->num_triangles;
9725                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9726                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9727                         }
9728                         surface2 = texturesurfacelist[j-1];
9729                         numvertices = endvertex - firstvertex;
9730                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9731                 }
9732         }
9733         else if (r_batchmode.integer == 1)
9734         {
9735                 for (i = 0;i < texturenumsurfaces;i = j)
9736                 {
9737                         surface = texturesurfacelist[i];
9738                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9739                                 if (texturesurfacelist[j] != surface2)
9740                                         break;
9741                         surface2 = texturesurfacelist[j-1];
9742                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9743                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9744                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9745                 }
9746         }
9747         else
9748         {
9749                 for (i = 0;i < texturenumsurfaces;i++)
9750                 {
9751                         surface = texturesurfacelist[i];
9752                         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);
9753                 }
9754         }
9755 }
9756
9757 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9758 {
9759         switch(vid.renderpath)
9760         {
9761         case RENDERPATH_CGGL:
9762 #ifdef SUPPORTCG
9763                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9764                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9765 #endif
9766                 break;
9767         case RENDERPATH_GL20:
9768                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9769                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9770                 break;
9771         case RENDERPATH_GL13:
9772         case RENDERPATH_GL11:
9773                 R_Mesh_TexBind(0, surface->lightmaptexture);
9774                 break;
9775         }
9776 }
9777
9778 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9779 {
9780         // pick the closest matching water plane and bind textures
9781         int planeindex, vertexindex;
9782         float d, bestd;
9783         vec3_t vert;
9784         const float *v;
9785         r_waterstate_waterplane_t *p, *bestp;
9786         bestd = 0;
9787         bestp = NULL;
9788         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9789         {
9790                 d = 0;
9791                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9792                 {
9793                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9794                         d += fabs(PlaneDiff(vert, &p->plane));
9795                 }
9796                 if (bestd > d || !bestp)
9797                 {
9798                         bestd = d;
9799                         bestp = p;
9800                 }
9801         }
9802         switch(vid.renderpath)
9803         {
9804         case RENDERPATH_CGGL:
9805 #ifdef SUPPORTCG
9806                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9807                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9808 #endif
9809                 break;
9810         case RENDERPATH_GL20:
9811                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9812                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9813                 break;
9814         case RENDERPATH_GL13:
9815         case RENDERPATH_GL11:
9816                 break;
9817         }
9818 }
9819
9820 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9821 {
9822         int i;
9823         const msurface_t *surface;
9824         if (r_waterstate.renderingscene)
9825                 return;
9826         for (i = 0;i < texturenumsurfaces;i++)
9827         {
9828                 surface = texturesurfacelist[i];
9829                 RSurf_BindLightmapForSurface(surface);
9830                 RSurf_BindReflectionForSurface(surface);
9831                 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);
9832         }
9833 }
9834
9835 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9836 {
9837         int i;
9838         int j;
9839         const msurface_t *surface = texturesurfacelist[0];
9840         const msurface_t *surface2;
9841         int firstvertex;
9842         int endvertex;
9843         int numvertices;
9844         int numtriangles;
9845         if (texturenumsurfaces == 1)
9846         {
9847                 RSurf_BindLightmapForSurface(surface);
9848                 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);
9849         }
9850         else if (r_batchmode.integer == 2)
9851         {
9852 #define MAXBATCHTRIANGLES 4096
9853                 int batchtriangles = 0;
9854                 static int batchelements[MAXBATCHTRIANGLES*3];
9855                 for (i = 0;i < texturenumsurfaces;i = j)
9856                 {
9857                         surface = texturesurfacelist[i];
9858                         RSurf_BindLightmapForSurface(surface);
9859                         j = i + 1;
9860                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9861                         {
9862                                 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);
9863                                 continue;
9864                         }
9865                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9866                         batchtriangles = surface->num_triangles;
9867                         firstvertex = surface->num_firstvertex;
9868                         endvertex = surface->num_firstvertex + surface->num_vertices;
9869                         for (;j < texturenumsurfaces;j++)
9870                         {
9871                                 surface2 = texturesurfacelist[j];
9872                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9873                                         break;
9874                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9875                                 batchtriangles += surface2->num_triangles;
9876                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9877                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9878                         }
9879                         surface2 = texturesurfacelist[j-1];
9880                         numvertices = endvertex - firstvertex;
9881                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9882                 }
9883         }
9884         else if (r_batchmode.integer == 1)
9885         {
9886 #if 0
9887                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9888                 for (i = 0;i < texturenumsurfaces;i = j)
9889                 {
9890                         surface = texturesurfacelist[i];
9891                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9892                                 if (texturesurfacelist[j] != surface2)
9893                                         break;
9894                         Con_Printf(" %i", j - i);
9895                 }
9896                 Con_Printf("\n");
9897                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9898 #endif
9899                 for (i = 0;i < texturenumsurfaces;i = j)
9900                 {
9901                         surface = texturesurfacelist[i];
9902                         RSurf_BindLightmapForSurface(surface);
9903                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9904                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9905                                         break;
9906 #if 0
9907                         Con_Printf(" %i", j - i);
9908 #endif
9909                         surface2 = texturesurfacelist[j-1];
9910                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9911                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9912                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9913                 }
9914 #if 0
9915                 Con_Printf("\n");
9916 #endif
9917         }
9918         else
9919         {
9920                 for (i = 0;i < texturenumsurfaces;i++)
9921                 {
9922                         surface = texturesurfacelist[i];
9923                         RSurf_BindLightmapForSurface(surface);
9924                         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);
9925                 }
9926         }
9927 }
9928
9929 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9930 {
9931         int j;
9932         int texturesurfaceindex;
9933         if (r_showsurfaces.integer == 2)
9934         {
9935                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9936                 {
9937                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9938                         for (j = 0;j < surface->num_triangles;j++)
9939                         {
9940                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9941                                 GL_Color(f, f, f, 1);
9942                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9943                         }
9944                 }
9945         }
9946         else
9947         {
9948                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9949                 {
9950                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9951                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9952                         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);
9953                         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);
9954                 }
9955         }
9956 }
9957
9958 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9959 {
9960         int texturesurfaceindex;
9961         int i;
9962         const float *v;
9963         float *c2;
9964         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9965         {
9966                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9967                 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)
9968                 {
9969                         c2[0] = 0.5;
9970                         c2[1] = 0.5;
9971                         c2[2] = 0.5;
9972                         c2[3] = 1;
9973                 }
9974         }
9975         rsurface.lightmapcolor4f = rsurface.array_color4f;
9976         rsurface.lightmapcolor4f_bufferobject = 0;
9977         rsurface.lightmapcolor4f_bufferoffset = 0;
9978 }
9979
9980 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9981 {
9982         int texturesurfaceindex;
9983         int i;
9984         float f;
9985         const float *v;
9986         const float *c;
9987         float *c2;
9988         if (rsurface.lightmapcolor4f)
9989         {
9990                 // generate color arrays for the surfaces in this list
9991                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9992                 {
9993                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9994                         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)
9995                         {
9996                                 f = RSurf_FogVertex(v);
9997                                 c2[0] = c[0] * f;
9998                                 c2[1] = c[1] * f;
9999                                 c2[2] = c[2] * f;
10000                                 c2[3] = c[3];
10001                         }
10002                 }
10003         }
10004         else
10005         {
10006                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10007                 {
10008                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10009                         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)
10010                         {
10011                                 f = RSurf_FogVertex(v);
10012                                 c2[0] = f;
10013                                 c2[1] = f;
10014                                 c2[2] = f;
10015                                 c2[3] = 1;
10016                         }
10017                 }
10018         }
10019         rsurface.lightmapcolor4f = rsurface.array_color4f;
10020         rsurface.lightmapcolor4f_bufferobject = 0;
10021         rsurface.lightmapcolor4f_bufferoffset = 0;
10022 }
10023
10024 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10025 {
10026         int texturesurfaceindex;
10027         int i;
10028         float f;
10029         const float *v;
10030         const float *c;
10031         float *c2;
10032         if (!rsurface.lightmapcolor4f)
10033                 return;
10034         // generate color arrays for the surfaces in this list
10035         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10036         {
10037                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10038                 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)
10039                 {
10040                         f = RSurf_FogVertex(v);
10041                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10042                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10043                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10044                         c2[3] = c[3];
10045                 }
10046         }
10047         rsurface.lightmapcolor4f = rsurface.array_color4f;
10048         rsurface.lightmapcolor4f_bufferobject = 0;
10049         rsurface.lightmapcolor4f_bufferoffset = 0;
10050 }
10051
10052 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10053 {
10054         int texturesurfaceindex;
10055         int i;
10056         const float *c;
10057         float *c2;
10058         if (!rsurface.lightmapcolor4f)
10059                 return;
10060         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10061         {
10062                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10063                 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)
10064                 {
10065                         c2[0] = c[0] * r;
10066                         c2[1] = c[1] * g;
10067                         c2[2] = c[2] * b;
10068                         c2[3] = c[3] * a;
10069                 }
10070         }
10071         rsurface.lightmapcolor4f = rsurface.array_color4f;
10072         rsurface.lightmapcolor4f_bufferobject = 0;
10073         rsurface.lightmapcolor4f_bufferoffset = 0;
10074 }
10075
10076 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10077 {
10078         int texturesurfaceindex;
10079         int i;
10080         const float *c;
10081         float *c2;
10082         if (!rsurface.lightmapcolor4f)
10083                 return;
10084         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10085         {
10086                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10087                 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)
10088                 {
10089                         c2[0] = c[0] + r_refdef.scene.ambient;
10090                         c2[1] = c[1] + r_refdef.scene.ambient;
10091                         c2[2] = c[2] + r_refdef.scene.ambient;
10092                         c2[3] = c[3];
10093                 }
10094         }
10095         rsurface.lightmapcolor4f = rsurface.array_color4f;
10096         rsurface.lightmapcolor4f_bufferobject = 0;
10097         rsurface.lightmapcolor4f_bufferoffset = 0;
10098 }
10099
10100 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10101 {
10102         // TODO: optimize
10103         rsurface.lightmapcolor4f = NULL;
10104         rsurface.lightmapcolor4f_bufferobject = 0;
10105         rsurface.lightmapcolor4f_bufferoffset = 0;
10106         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10107         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10108         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10109         GL_Color(r, g, b, a);
10110         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10111 }
10112
10113 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10114 {
10115         // TODO: optimize applyfog && applycolor case
10116         // just apply fog if necessary, and tint the fog color array if necessary
10117         rsurface.lightmapcolor4f = NULL;
10118         rsurface.lightmapcolor4f_bufferobject = 0;
10119         rsurface.lightmapcolor4f_bufferoffset = 0;
10120         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10121         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10122         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10123         GL_Color(r, g, b, a);
10124         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10125 }
10126
10127 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10128 {
10129         int texturesurfaceindex;
10130         int i;
10131         float *c;
10132         // TODO: optimize
10133         if (texturesurfacelist[0]->lightmapinfo)
10134         {
10135                 // generate color arrays for the surfaces in this list
10136                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10137                 {
10138                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10139                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10140                         {
10141                                 if (surface->lightmapinfo->samples)
10142                                 {
10143                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10144                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10145                                         VectorScale(lm, scale, c);
10146                                         if (surface->lightmapinfo->styles[1] != 255)
10147                                         {
10148                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10149                                                 lm += size3;
10150                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10151                                                 VectorMA(c, scale, lm, c);
10152                                                 if (surface->lightmapinfo->styles[2] != 255)
10153                                                 {
10154                                                         lm += size3;
10155                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10156                                                         VectorMA(c, scale, lm, c);
10157                                                         if (surface->lightmapinfo->styles[3] != 255)
10158                                                         {
10159                                                                 lm += size3;
10160                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10161                                                                 VectorMA(c, scale, lm, c);
10162                                                         }
10163                                                 }
10164                                         }
10165                                 }
10166                                 else
10167                                         VectorClear(c);
10168                                 c[3] = 1;
10169                         }
10170                 }
10171                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10172                 rsurface.lightmapcolor4f_bufferobject = 0;
10173                 rsurface.lightmapcolor4f_bufferoffset = 0;
10174         }
10175         else
10176         {
10177                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10178                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10179                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10180         }
10181         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10182         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10183         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10184         GL_Color(r, g, b, a);
10185         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10186 }
10187
10188 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10189 {
10190         int texturesurfaceindex;
10191         int i;
10192         float f;
10193         float alpha;
10194         const float *v;
10195         const float *n;
10196         float *c;
10197         vec3_t ambientcolor;
10198         vec3_t diffusecolor;
10199         vec3_t lightdir;
10200         // TODO: optimize
10201         // model lighting
10202         VectorCopy(rsurface.modellight_lightdir, lightdir);
10203         f = 0.5f * r_refdef.lightmapintensity;
10204         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10205         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10206         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10207         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10208         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10209         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10210         alpha = *a;
10211         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10212         {
10213                 // generate color arrays for the surfaces in this list
10214                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10215                 {
10216                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10217                         int numverts = surface->num_vertices;
10218                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10219                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10220                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10221                         // q3-style directional shading
10222                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10223                         {
10224                                 if ((f = DotProduct(n, lightdir)) > 0)
10225                                         VectorMA(ambientcolor, f, diffusecolor, c);
10226                                 else
10227                                         VectorCopy(ambientcolor, c);
10228                                 c[3] = alpha;
10229                         }
10230                 }
10231                 *r = 1;
10232                 *g = 1;
10233                 *b = 1;
10234                 *a = 1;
10235                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10236                 rsurface.lightmapcolor4f_bufferobject = 0;
10237                 rsurface.lightmapcolor4f_bufferoffset = 0;
10238                 *applycolor = false;
10239         }
10240         else
10241         {
10242                 *r = ambientcolor[0];
10243                 *g = ambientcolor[1];
10244                 *b = ambientcolor[2];
10245                 rsurface.lightmapcolor4f = NULL;
10246                 rsurface.lightmapcolor4f_bufferobject = 0;
10247                 rsurface.lightmapcolor4f_bufferoffset = 0;
10248         }
10249 }
10250
10251 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10252 {
10253         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10254         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10255         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10256         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10257         GL_Color(r, g, b, a);
10258         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10259 }
10260
10261 void RSurf_SetupDepthAndCulling(void)
10262 {
10263         // submodels are biased to avoid z-fighting with world surfaces that they
10264         // may be exactly overlapping (avoids z-fighting artifacts on certain
10265         // doors and things in Quake maps)
10266         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10267         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10268         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10269         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10270 }
10271
10272 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10273 {
10274         // transparent sky would be ridiculous
10275         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10276                 return;
10277         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10278         skyrenderlater = true;
10279         RSurf_SetupDepthAndCulling();
10280         GL_DepthMask(true);
10281         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10282         // skymasking on them, and Quake3 never did sky masking (unlike
10283         // software Quake and software Quake2), so disable the sky masking
10284         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10285         // and skymasking also looks very bad when noclipping outside the
10286         // level, so don't use it then either.
10287         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10288         {
10289                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10290                 R_Mesh_ColorPointer(NULL, 0, 0);
10291                 R_Mesh_ResetTextureState();
10292                 if (skyrendermasked)
10293                 {
10294                         R_SetupShader_DepthOrShadow();
10295                         // depth-only (masking)
10296                         GL_ColorMask(0,0,0,0);
10297                         // just to make sure that braindead drivers don't draw
10298                         // anything despite that colormask...
10299                         GL_BlendFunc(GL_ZERO, GL_ONE);
10300                 }
10301                 else
10302                 {
10303                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10304                         // fog sky
10305                         GL_BlendFunc(GL_ONE, GL_ZERO);
10306                 }
10307                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10308                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10309                 if (skyrendermasked)
10310                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10311         }
10312         R_Mesh_ResetTextureState();
10313         GL_Color(1, 1, 1, 1);
10314 }
10315
10316 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10317 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10318 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10319 {
10320         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10321         if (prepass)
10322         {
10323                 // render screenspace normalmap to texture
10324                 GL_DepthMask(true);
10325                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10326                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10327         }
10328         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10329         {
10330                 // render water or distortion background, then blend surface on top
10331                 GL_DepthMask(true);
10332                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10333                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10334                 GL_DepthMask(false);
10335                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10336                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10337         }
10338         else
10339         {
10340                 // render surface normally
10341                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10342                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10343                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10344                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10345                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10346                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10347                 else
10348                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10349         }
10350 }
10351
10352 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10353 {
10354         // OpenGL 1.3 path - anything not completely ancient
10355         int texturesurfaceindex;
10356         qboolean applycolor;
10357         qboolean applyfog;
10358         int layerindex;
10359         const texturelayer_t *layer;
10360         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10361
10362         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10363         {
10364                 vec4_t layercolor;
10365                 int layertexrgbscale;
10366                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10367                 {
10368                         if (layerindex == 0)
10369                                 GL_AlphaTest(true);
10370                         else
10371                         {
10372                                 GL_AlphaTest(false);
10373                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10374                         }
10375                 }
10376                 GL_DepthMask(layer->depthmask && writedepth);
10377                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10378                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10379                 {
10380                         layertexrgbscale = 4;
10381                         VectorScale(layer->color, 0.25f, layercolor);
10382                 }
10383                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10384                 {
10385                         layertexrgbscale = 2;
10386                         VectorScale(layer->color, 0.5f, layercolor);
10387                 }
10388                 else
10389                 {
10390                         layertexrgbscale = 1;
10391                         VectorScale(layer->color, 1.0f, layercolor);
10392                 }
10393                 layercolor[3] = layer->color[3];
10394                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10395                 R_Mesh_ColorPointer(NULL, 0, 0);
10396                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10397                 switch (layer->type)
10398                 {
10399                 case TEXTURELAYERTYPE_LITTEXTURE:
10400                         // single-pass lightmapped texture with 2x rgbscale
10401                         //R_Mesh_TexBind(0, r_texture_white);
10402                         R_Mesh_TexMatrix(0, NULL);
10403                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10404                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10405                         R_Mesh_TexBind(1, layer->texture);
10406                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10407                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10408                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10409                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10410                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10411                         else if (rsurface.uselightmaptexture)
10412                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10413                         else
10414                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10415                         break;
10416                 case TEXTURELAYERTYPE_TEXTURE:
10417                         // singletexture unlit texture with transparency support
10418                         R_Mesh_TexBind(0, layer->texture);
10419                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10420                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10421                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10422                         R_Mesh_TexBind(1, 0);
10423                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10424                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10425                         break;
10426                 case TEXTURELAYERTYPE_FOG:
10427                         // singletexture fogging
10428                         if (layer->texture)
10429                         {
10430                                 R_Mesh_TexBind(0, layer->texture);
10431                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10432                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10433                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10434                         }
10435                         else
10436                         {
10437                                 R_Mesh_TexBind(0, 0);
10438                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10439                         }
10440                         R_Mesh_TexBind(1, 0);
10441                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10442                         // generate a color array for the fog pass
10443                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10444                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10445                         {
10446                                 int i;
10447                                 float f;
10448                                 const float *v;
10449                                 float *c;
10450                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10451                                 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)
10452                                 {
10453                                         f = 1 - RSurf_FogVertex(v);
10454                                         c[0] = layercolor[0];
10455                                         c[1] = layercolor[1];
10456                                         c[2] = layercolor[2];
10457                                         c[3] = f * layercolor[3];
10458                                 }
10459                         }
10460                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10461                         break;
10462                 default:
10463                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10464                 }
10465         }
10466         CHECKGLERROR
10467         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10468         {
10469                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10470                 GL_AlphaTest(false);
10471         }
10472 }
10473
10474 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10475 {
10476         // OpenGL 1.1 - crusty old voodoo path
10477         int texturesurfaceindex;
10478         qboolean applyfog;
10479         int layerindex;
10480         const texturelayer_t *layer;
10481         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10482
10483         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10484         {
10485                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10486                 {
10487                         if (layerindex == 0)
10488                                 GL_AlphaTest(true);
10489                         else
10490                         {
10491                                 GL_AlphaTest(false);
10492                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10493                         }
10494                 }
10495                 GL_DepthMask(layer->depthmask && writedepth);
10496                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10497                 R_Mesh_ColorPointer(NULL, 0, 0);
10498                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10499                 switch (layer->type)
10500                 {
10501                 case TEXTURELAYERTYPE_LITTEXTURE:
10502                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10503                         {
10504                                 // two-pass lit texture with 2x rgbscale
10505                                 // first the lightmap pass
10506                                 //R_Mesh_TexBind(0, r_texture_white);
10507                                 R_Mesh_TexMatrix(0, NULL);
10508                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10509                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10510                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10511                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10512                                 else if (rsurface.uselightmaptexture)
10513                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10514                                 else
10515                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10516                                 // then apply the texture to it
10517                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10518                                 R_Mesh_TexBind(0, layer->texture);
10519                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10520                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10521                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10522                                 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);
10523                         }
10524                         else
10525                         {
10526                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10527                                 R_Mesh_TexBind(0, layer->texture);
10528                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10529                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10530                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10531                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10532                                         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);
10533                                 else
10534                                         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);
10535                         }
10536                         break;
10537                 case TEXTURELAYERTYPE_TEXTURE:
10538                         // singletexture unlit texture with transparency support
10539                         R_Mesh_TexBind(0, layer->texture);
10540                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10541                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10542                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10543                         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);
10544                         break;
10545                 case TEXTURELAYERTYPE_FOG:
10546                         // singletexture fogging
10547                         if (layer->texture)
10548                         {
10549                                 R_Mesh_TexBind(0, layer->texture);
10550                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10551                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10552                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10553                         }
10554                         else
10555                         {
10556                                 R_Mesh_TexBind(0, 0);
10557                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10558                         }
10559                         // generate a color array for the fog pass
10560                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10561                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10562                         {
10563                                 int i;
10564                                 float f;
10565                                 const float *v;
10566                                 float *c;
10567                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10568                                 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)
10569                                 {
10570                                         f = 1 - RSurf_FogVertex(v);
10571                                         c[0] = layer->color[0];
10572                                         c[1] = layer->color[1];
10573                                         c[2] = layer->color[2];
10574                                         c[3] = f * layer->color[3];
10575                                 }
10576                         }
10577                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10578                         break;
10579                 default:
10580                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10581                 }
10582         }
10583         CHECKGLERROR
10584         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10585         {
10586                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10587                 GL_AlphaTest(false);
10588         }
10589 }
10590
10591 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10592 {
10593         float c[4];
10594
10595         GL_AlphaTest(false);
10596         R_Mesh_ColorPointer(NULL, 0, 0);
10597         R_Mesh_ResetTextureState();
10598         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10599
10600         if(rsurface.texture && rsurface.texture->currentskinframe)
10601         {
10602                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10603                 c[3] *= rsurface.texture->currentalpha;
10604         }
10605         else
10606         {
10607                 c[0] = 1;
10608                 c[1] = 0;
10609                 c[2] = 1;
10610                 c[3] = 1;
10611         }
10612
10613         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10614         {
10615                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10616                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10617                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10618         }
10619
10620         // brighten it up (as texture value 127 means "unlit")
10621         c[0] *= 2 * r_refdef.view.colorscale;
10622         c[1] *= 2 * r_refdef.view.colorscale;
10623         c[2] *= 2 * r_refdef.view.colorscale;
10624
10625         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10626                 c[3] *= r_wateralpha.value;
10627
10628         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10629         {
10630                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10631                 GL_DepthMask(false);
10632         }
10633         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10634         {
10635                 GL_BlendFunc(GL_ONE, GL_ONE);
10636                 GL_DepthMask(false);
10637         }
10638         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10639         {
10640                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10641                 GL_DepthMask(false);
10642         }
10643         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10644         {
10645                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10646                 GL_DepthMask(false);
10647         }
10648         else
10649         {
10650                 GL_BlendFunc(GL_ONE, GL_ZERO);
10651                 GL_DepthMask(writedepth);
10652         }
10653
10654         rsurface.lightmapcolor4f = NULL;
10655
10656         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10657         {
10658                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10659
10660                 rsurface.lightmapcolor4f = NULL;
10661                 rsurface.lightmapcolor4f_bufferobject = 0;
10662                 rsurface.lightmapcolor4f_bufferoffset = 0;
10663         }
10664         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10665         {
10666                 qboolean applycolor = true;
10667                 float one = 1.0;
10668
10669                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10670
10671                 r_refdef.lightmapintensity = 1;
10672                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10673                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10674         }
10675         else
10676         {
10677                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10678
10679                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10680                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10681                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10682         }
10683
10684         if(!rsurface.lightmapcolor4f)
10685                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10686
10687         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10688         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10689         if(r_refdef.fogenabled)
10690                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10691
10692         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10693         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10694 }
10695
10696 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10697 {
10698         CHECKGLERROR
10699         RSurf_SetupDepthAndCulling();
10700         if (r_showsurfaces.integer == 3 && !prepass)
10701         {
10702                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10703                 return;
10704         }
10705         switch (vid.renderpath)
10706         {
10707         case RENDERPATH_GL20:
10708         case RENDERPATH_CGGL:
10709                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10710                 break;
10711         case RENDERPATH_GL13:
10712                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10713                 break;
10714         case RENDERPATH_GL11:
10715                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10716                 break;
10717         }
10718         CHECKGLERROR
10719 }
10720
10721 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10722 {
10723         CHECKGLERROR
10724         RSurf_SetupDepthAndCulling();
10725         if (r_showsurfaces.integer == 3 && !prepass)
10726         {
10727                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10728                 return;
10729         }
10730         switch (vid.renderpath)
10731         {
10732         case RENDERPATH_GL20:
10733         case RENDERPATH_CGGL:
10734                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10735                 break;
10736         case RENDERPATH_GL13:
10737                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10738                 break;
10739         case RENDERPATH_GL11:
10740                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10741                 break;
10742         }
10743         CHECKGLERROR
10744 }
10745
10746 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10747 {
10748         int i, j;
10749         int texturenumsurfaces, endsurface;
10750         texture_t *texture;
10751         const msurface_t *surface;
10752         const msurface_t *texturesurfacelist[256];
10753
10754         // if the model is static it doesn't matter what value we give for
10755         // wantnormals and wanttangents, so this logic uses only rules applicable
10756         // to a model, knowing that they are meaningless otherwise
10757         if (ent == r_refdef.scene.worldentity)
10758                 RSurf_ActiveWorldEntity();
10759         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10760                 RSurf_ActiveModelEntity(ent, false, false, false);
10761         else
10762         {
10763                 switch (vid.renderpath)
10764                 {
10765                 case RENDERPATH_GL20:
10766                 case RENDERPATH_CGGL:
10767                         RSurf_ActiveModelEntity(ent, true, true, false);
10768                         break;
10769                 case RENDERPATH_GL13:
10770                 case RENDERPATH_GL11:
10771                         RSurf_ActiveModelEntity(ent, true, false, false);
10772                         break;
10773                 }
10774         }
10775
10776         if (r_transparentdepthmasking.integer)
10777         {
10778                 qboolean setup = false;
10779                 for (i = 0;i < numsurfaces;i = j)
10780                 {
10781                         j = i + 1;
10782                         surface = rsurface.modelsurfaces + surfacelist[i];
10783                         texture = surface->texture;
10784                         rsurface.texture = R_GetCurrentTexture(texture);
10785                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10786                         // scan ahead until we find a different texture
10787                         endsurface = min(i + 1024, numsurfaces);
10788                         texturenumsurfaces = 0;
10789                         texturesurfacelist[texturenumsurfaces++] = surface;
10790                         for (;j < endsurface;j++)
10791                         {
10792                                 surface = rsurface.modelsurfaces + surfacelist[j];
10793                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10794                                         break;
10795                                 texturesurfacelist[texturenumsurfaces++] = surface;
10796                         }
10797                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10798                                 continue;
10799                         // render the range of surfaces as depth
10800                         if (!setup)
10801                         {
10802                                 setup = true;
10803                                 GL_ColorMask(0,0,0,0);
10804                                 GL_Color(1,1,1,1);
10805                                 GL_DepthTest(true);
10806                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10807                                 GL_DepthMask(true);
10808                                 GL_AlphaTest(false);
10809                                 R_Mesh_ColorPointer(NULL, 0, 0);
10810                                 R_Mesh_ResetTextureState();
10811                                 R_SetupShader_DepthOrShadow();
10812                         }
10813                         RSurf_SetupDepthAndCulling();
10814                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10815                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10816                 }
10817                 if (setup)
10818                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10819         }
10820
10821         for (i = 0;i < numsurfaces;i = j)
10822         {
10823                 j = i + 1;
10824                 surface = rsurface.modelsurfaces + surfacelist[i];
10825                 texture = surface->texture;
10826                 rsurface.texture = R_GetCurrentTexture(texture);
10827                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10828                 // scan ahead until we find a different texture
10829                 endsurface = min(i + 1024, numsurfaces);
10830                 texturenumsurfaces = 0;
10831                 texturesurfacelist[texturenumsurfaces++] = surface;
10832                 for (;j < endsurface;j++)
10833                 {
10834                         surface = rsurface.modelsurfaces + surfacelist[j];
10835                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10836                                 break;
10837                         texturesurfacelist[texturenumsurfaces++] = surface;
10838                 }
10839                 // render the range of surfaces
10840                 if (ent == r_refdef.scene.worldentity)
10841                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10842                 else
10843                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10844         }
10845         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10846         GL_AlphaTest(false);
10847 }
10848
10849 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10850 {
10851         // transparent surfaces get pushed off into the transparent queue
10852         int surfacelistindex;
10853         const msurface_t *surface;
10854         vec3_t tempcenter, center;
10855         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10856         {
10857                 surface = texturesurfacelist[surfacelistindex];
10858                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10859                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10860                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10861                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10862                 if (queueentity->transparent_offset) // transparent offset
10863                 {
10864                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10865                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10866                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10867                 }
10868                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10869         }
10870 }
10871
10872 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10873 {
10874         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10875         CHECKGLERROR
10876         if (depthonly)
10877         {
10878                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10879                         return;
10880                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10881                         return;
10882                 RSurf_SetupDepthAndCulling();
10883                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10884                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10885         }
10886         else if (prepass)
10887         {
10888                 if (!rsurface.texture->currentnumlayers)
10889                         return;
10890                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10891                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10892                 else
10893                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10894         }
10895         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10896         {
10897                 RSurf_SetupDepthAndCulling();
10898                 GL_AlphaTest(false);
10899                 R_Mesh_ColorPointer(NULL, 0, 0);
10900                 R_Mesh_ResetTextureState();
10901                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10902                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10903                 GL_DepthMask(true);
10904                 GL_BlendFunc(GL_ONE, GL_ZERO);
10905                 GL_Color(0, 0, 0, 1);
10906                 GL_DepthTest(writedepth);
10907                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10908         }
10909         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10910         {
10911                 RSurf_SetupDepthAndCulling();
10912                 GL_AlphaTest(false);
10913                 R_Mesh_ColorPointer(NULL, 0, 0);
10914                 R_Mesh_ResetTextureState();
10915                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10916                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10917                 GL_DepthMask(true);
10918                 GL_BlendFunc(GL_ONE, GL_ZERO);
10919                 GL_DepthTest(true);
10920                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10921         }
10922         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10923                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10924         else if (!rsurface.texture->currentnumlayers)
10925                 return;
10926         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10927         {
10928                 // in the deferred case, transparent surfaces were queued during prepass
10929                 if (!r_shadow_usingdeferredprepass)
10930                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10931         }
10932         else
10933         {
10934                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10935                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10936         }
10937         CHECKGLERROR
10938 }
10939
10940 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10941 {
10942         int i, j;
10943         texture_t *texture;
10944         // break the surface list down into batches by texture and use of lightmapping
10945         for (i = 0;i < numsurfaces;i = j)
10946         {
10947                 j = i + 1;
10948                 // texture is the base texture pointer, rsurface.texture is the
10949                 // current frame/skin the texture is directing us to use (for example
10950                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10951                 // use skin 1 instead)
10952                 texture = surfacelist[i]->texture;
10953                 rsurface.texture = R_GetCurrentTexture(texture);
10954                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10955                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10956                 {
10957                         // if this texture is not the kind we want, skip ahead to the next one
10958                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10959                                 ;
10960                         continue;
10961                 }
10962                 // simply scan ahead until we find a different texture or lightmap state
10963                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10964                         ;
10965                 // render the range of surfaces
10966                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10967         }
10968 }
10969
10970 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10971 {
10972         CHECKGLERROR
10973         if (depthonly)
10974         {
10975                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10976                         return;
10977                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10978                         return;
10979                 RSurf_SetupDepthAndCulling();
10980                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10981                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10982         }
10983         else if (prepass)
10984         {
10985                 if (!rsurface.texture->currentnumlayers)
10986                         return;
10987                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10988                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10989                 else
10990                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10991         }
10992         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10993         {
10994                 RSurf_SetupDepthAndCulling();
10995                 GL_AlphaTest(false);
10996                 R_Mesh_ColorPointer(NULL, 0, 0);
10997                 R_Mesh_ResetTextureState();
10998                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10999                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11000                 GL_DepthMask(true);
11001                 GL_BlendFunc(GL_ONE, GL_ZERO);
11002                 GL_Color(0, 0, 0, 1);
11003                 GL_DepthTest(writedepth);
11004                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11005         }
11006         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11007         {
11008                 RSurf_SetupDepthAndCulling();
11009                 GL_AlphaTest(false);
11010                 R_Mesh_ColorPointer(NULL, 0, 0);
11011                 R_Mesh_ResetTextureState();
11012                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11013                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11014                 GL_DepthMask(true);
11015                 GL_BlendFunc(GL_ONE, GL_ZERO);
11016                 GL_DepthTest(true);
11017                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11018         }
11019         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11020                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11021         else if (!rsurface.texture->currentnumlayers)
11022                 return;
11023         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11024         {
11025                 // in the deferred case, transparent surfaces were queued during prepass
11026                 if (!r_shadow_usingdeferredprepass)
11027                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11028         }
11029         else
11030         {
11031                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11032                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11033         }
11034         CHECKGLERROR
11035 }
11036
11037 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11038 {
11039         int i, j;
11040         texture_t *texture;
11041         // break the surface list down into batches by texture and use of lightmapping
11042         for (i = 0;i < numsurfaces;i = j)
11043         {
11044                 j = i + 1;
11045                 // texture is the base texture pointer, rsurface.texture is the
11046                 // current frame/skin the texture is directing us to use (for example
11047                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11048                 // use skin 1 instead)
11049                 texture = surfacelist[i]->texture;
11050                 rsurface.texture = R_GetCurrentTexture(texture);
11051                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11052                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11053                 {
11054                         // if this texture is not the kind we want, skip ahead to the next one
11055                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11056                                 ;
11057                         continue;
11058                 }
11059                 // simply scan ahead until we find a different texture or lightmap state
11060                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11061                         ;
11062                 // render the range of surfaces
11063                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11064         }
11065 }
11066
11067 float locboxvertex3f[6*4*3] =
11068 {
11069         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11070         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11071         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11072         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11073         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11074         1,0,0, 0,0,0, 0,1,0, 1,1,0
11075 };
11076
11077 unsigned short locboxelements[6*2*3] =
11078 {
11079          0, 1, 2, 0, 2, 3,
11080          4, 5, 6, 4, 6, 7,
11081          8, 9,10, 8,10,11,
11082         12,13,14, 12,14,15,
11083         16,17,18, 16,18,19,
11084         20,21,22, 20,22,23
11085 };
11086
11087 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11088 {
11089         int i, j;
11090         cl_locnode_t *loc = (cl_locnode_t *)ent;
11091         vec3_t mins, size;
11092         float vertex3f[6*4*3];
11093         CHECKGLERROR
11094         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11095         GL_DepthMask(false);
11096         GL_DepthRange(0, 1);
11097         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11098         GL_DepthTest(true);
11099         GL_CullFace(GL_NONE);
11100         R_EntityMatrix(&identitymatrix);
11101
11102         R_Mesh_VertexPointer(vertex3f, 0, 0);
11103         R_Mesh_ColorPointer(NULL, 0, 0);
11104         R_Mesh_ResetTextureState();
11105         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11106
11107         i = surfacelist[0];
11108         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11109                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11110                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11111                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11112
11113         if (VectorCompare(loc->mins, loc->maxs))
11114         {
11115                 VectorSet(size, 2, 2, 2);
11116                 VectorMA(loc->mins, -0.5f, size, mins);
11117         }
11118         else
11119         {
11120                 VectorCopy(loc->mins, mins);
11121                 VectorSubtract(loc->maxs, loc->mins, size);
11122         }
11123
11124         for (i = 0;i < 6*4*3;)
11125                 for (j = 0;j < 3;j++, i++)
11126                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11127
11128         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11129 }
11130
11131 void R_DrawLocs(void)
11132 {
11133         int index;
11134         cl_locnode_t *loc, *nearestloc;
11135         vec3_t center;
11136         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11137         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11138         {
11139                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11140                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11141         }
11142 }
11143
11144 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11145 {
11146         if (decalsystem->decals)
11147                 Mem_Free(decalsystem->decals);
11148         memset(decalsystem, 0, sizeof(*decalsystem));
11149 }
11150
11151 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)
11152 {
11153         tridecal_t *decal;
11154         tridecal_t *decals;
11155         int i;
11156         int maxdecals;
11157
11158         // expand or initialize the system
11159         if (decalsystem->maxdecals <= decalsystem->numdecals)
11160         {
11161                 decalsystem_t old = *decalsystem;
11162                 qboolean useshortelements;
11163                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11164                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11165                 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)));
11166                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11167                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11168                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11169                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11170                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11171                 if (decalsystem->numdecals)
11172                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11173                 if (old.decals)
11174                         Mem_Free(old.decals);
11175                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11176                         decalsystem->element3i[i] = i;
11177                 if (useshortelements)
11178                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11179                                 decalsystem->element3s[i] = i;
11180         }
11181
11182         // grab a decal and search for another free slot for the next one
11183         maxdecals = decalsystem->maxdecals;
11184         decals = decalsystem->decals;
11185         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11186         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11187                 ;
11188         decalsystem->freedecal = i;
11189         if (decalsystem->numdecals <= i)
11190                 decalsystem->numdecals = i + 1;
11191
11192         // initialize the decal
11193         decal->lived = 0;
11194         decal->triangleindex = triangleindex;
11195         decal->surfaceindex = surfaceindex;
11196         decal->decalsequence = decalsequence;
11197         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11198         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11199         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11200         decal->color4ub[0][3] = 255;
11201         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11202         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11203         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11204         decal->color4ub[1][3] = 255;
11205         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11206         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11207         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11208         decal->color4ub[2][3] = 255;
11209         decal->vertex3f[0][0] = v0[0];
11210         decal->vertex3f[0][1] = v0[1];
11211         decal->vertex3f[0][2] = v0[2];
11212         decal->vertex3f[1][0] = v1[0];
11213         decal->vertex3f[1][1] = v1[1];
11214         decal->vertex3f[1][2] = v1[2];
11215         decal->vertex3f[2][0] = v2[0];
11216         decal->vertex3f[2][1] = v2[1];
11217         decal->vertex3f[2][2] = v2[2];
11218         decal->texcoord2f[0][0] = t0[0];
11219         decal->texcoord2f[0][1] = t0[1];
11220         decal->texcoord2f[1][0] = t1[0];
11221         decal->texcoord2f[1][1] = t1[1];
11222         decal->texcoord2f[2][0] = t2[0];
11223         decal->texcoord2f[2][1] = t2[1];
11224 }
11225
11226 extern cvar_t cl_decals_bias;
11227 extern cvar_t cl_decals_models;
11228 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11229 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)
11230 {
11231         matrix4x4_t projection;
11232         decalsystem_t *decalsystem;
11233         qboolean dynamic;
11234         dp_model_t *model;
11235         const float *vertex3f;
11236         const msurface_t *surface;
11237         const msurface_t *surfaces;
11238         const int *surfacelist;
11239         const texture_t *texture;
11240         int numvertices;
11241         int numtriangles;
11242         int numsurfacelist;
11243         int surfacelistindex;
11244         int surfaceindex;
11245         int triangleindex;
11246         int decalsurfaceindex;
11247         int cornerindex;
11248         int index;
11249         int numpoints;
11250         const int *e;
11251         float localorigin[3];
11252         float localnormal[3];
11253         float localmins[3];
11254         float localmaxs[3];
11255         float localsize;
11256         float ilocalsize;
11257         float v[9][3];
11258         float tc[9][2];
11259         float c[9][4];
11260         //float normal[3];
11261         float planes[6][4];
11262         float f;
11263         float points[2][9][3];
11264         float angles[3];
11265         float temp[3];
11266
11267         decalsystem = &ent->decalsystem;
11268         model = ent->model;
11269         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11270         {
11271                 R_DecalSystem_Reset(&ent->decalsystem);
11272                 return;
11273         }
11274
11275         if (!model->brush.data_nodes && !cl_decals_models.integer)
11276         {
11277                 if (decalsystem->model)
11278                         R_DecalSystem_Reset(decalsystem);
11279                 return;
11280         }
11281
11282         if (decalsystem->model != model)
11283                 R_DecalSystem_Reset(decalsystem);
11284         decalsystem->model = model;
11285
11286         RSurf_ActiveModelEntity(ent, false, false, false);
11287
11288         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11289         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11290         VectorNormalize(localnormal);
11291         localsize = worldsize*rsurface.inversematrixscale;
11292         ilocalsize = 1.0f / localsize;
11293         localmins[0] = localorigin[0] - localsize;
11294         localmins[1] = localorigin[1] - localsize;
11295         localmins[2] = localorigin[2] - localsize;
11296         localmaxs[0] = localorigin[0] + localsize;
11297         localmaxs[1] = localorigin[1] + localsize;
11298         localmaxs[2] = localorigin[2] + localsize;
11299
11300         //VectorCopy(localnormal, planes[4]);
11301         //VectorVectors(planes[4], planes[2], planes[0]);
11302         AnglesFromVectors(angles, localnormal, NULL, false);
11303         AngleVectors(angles, planes[0], planes[2], planes[4]);
11304         VectorNegate(planes[0], planes[1]);
11305         VectorNegate(planes[2], planes[3]);
11306         VectorNegate(planes[4], planes[5]);
11307         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11308         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11309         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11310         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11311         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11312         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11313
11314 #if 1
11315 // works
11316 {
11317         matrix4x4_t forwardprojection;
11318         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11319         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11320 }
11321 #else
11322 // broken
11323 {
11324         float projectionvector[4][3];
11325         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11326         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11327         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11328         projectionvector[0][0] = planes[0][0] * ilocalsize;
11329         projectionvector[0][1] = planes[1][0] * ilocalsize;
11330         projectionvector[0][2] = planes[2][0] * ilocalsize;
11331         projectionvector[1][0] = planes[0][1] * ilocalsize;
11332         projectionvector[1][1] = planes[1][1] * ilocalsize;
11333         projectionvector[1][2] = planes[2][1] * ilocalsize;
11334         projectionvector[2][0] = planes[0][2] * ilocalsize;
11335         projectionvector[2][1] = planes[1][2] * ilocalsize;
11336         projectionvector[2][2] = planes[2][2] * ilocalsize;
11337         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11338         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11339         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11340         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11341 }
11342 #endif
11343
11344         dynamic = model->surfmesh.isanimated;
11345         vertex3f = rsurface.modelvertex3f;
11346         numsurfacelist = model->nummodelsurfaces;
11347         surfacelist = model->sortedmodelsurfaces;
11348         surfaces = model->data_surfaces;
11349         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11350         {
11351                 surfaceindex = surfacelist[surfacelistindex];
11352                 surface = surfaces + surfaceindex;
11353                 // skip transparent surfaces
11354                 texture = surface->texture;
11355                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11356                         continue;
11357                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11358                         continue;
11359                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11360                         continue;
11361                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11362                 numvertices = surface->num_vertices;
11363                 numtriangles = surface->num_triangles;
11364                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11365                 {
11366                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11367                         {
11368                                 index = 3*e[cornerindex];
11369                                 VectorCopy(vertex3f + index, v[cornerindex]);
11370                         }
11371                         // cull backfaces
11372                         //TriangleNormal(v[0], v[1], v[2], normal);
11373                         //if (DotProduct(normal, localnormal) < 0.0f)
11374                         //      continue;
11375                         // clip by each of the box planes formed from the projection matrix
11376                         // if anything survives, we emit the decal
11377                         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]);
11378                         if (numpoints < 3)
11379                                 continue;
11380                         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]);
11381                         if (numpoints < 3)
11382                                 continue;
11383                         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]);
11384                         if (numpoints < 3)
11385                                 continue;
11386                         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]);
11387                         if (numpoints < 3)
11388                                 continue;
11389                         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]);
11390                         if (numpoints < 3)
11391                                 continue;
11392                         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]);
11393                         if (numpoints < 3)
11394                                 continue;
11395                         // some part of the triangle survived, so we have to accept it...
11396                         if (dynamic)
11397                         {
11398                                 // dynamic always uses the original triangle
11399                                 numpoints = 3;
11400                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11401                                 {
11402                                         index = 3*e[cornerindex];
11403                                         VectorCopy(vertex3f + index, v[cornerindex]);
11404                                 }
11405                         }
11406                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11407                         {
11408                                 // convert vertex positions to texcoords
11409                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11410                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11411                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11412                                 // calculate distance fade from the projection origin
11413                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11414                                 f = bound(0.0f, f, 1.0f);
11415                                 c[cornerindex][0] = r * f;
11416                                 c[cornerindex][1] = g * f;
11417                                 c[cornerindex][2] = b * f;
11418                                 c[cornerindex][3] = 1.0f;
11419                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11420                         }
11421                         if (dynamic)
11422                                 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);
11423                         else
11424                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11425                                         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);
11426                 }
11427         }
11428 }
11429
11430 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11431 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)
11432 {
11433         int renderentityindex;
11434         float worldmins[3];
11435         float worldmaxs[3];
11436         entity_render_t *ent;
11437
11438         if (!cl_decals_newsystem.integer)
11439                 return;
11440
11441         worldmins[0] = worldorigin[0] - worldsize;
11442         worldmins[1] = worldorigin[1] - worldsize;
11443         worldmins[2] = worldorigin[2] - worldsize;
11444         worldmaxs[0] = worldorigin[0] + worldsize;
11445         worldmaxs[1] = worldorigin[1] + worldsize;
11446         worldmaxs[2] = worldorigin[2] + worldsize;
11447
11448         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11449
11450         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11451         {
11452                 ent = r_refdef.scene.entities[renderentityindex];
11453                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11454                         continue;
11455
11456                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11457         }
11458 }
11459
11460 typedef struct r_decalsystem_splatqueue_s
11461 {
11462         vec3_t worldorigin;
11463         vec3_t worldnormal;
11464         float color[4];
11465         float tcrange[4];
11466         float worldsize;
11467         int decalsequence;
11468 }
11469 r_decalsystem_splatqueue_t;
11470
11471 int r_decalsystem_numqueued = 0;
11472 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11473
11474 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)
11475 {
11476         r_decalsystem_splatqueue_t *queue;
11477
11478         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11479                 return;
11480
11481         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11482         VectorCopy(worldorigin, queue->worldorigin);
11483         VectorCopy(worldnormal, queue->worldnormal);
11484         Vector4Set(queue->color, r, g, b, a);
11485         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11486         queue->worldsize = worldsize;
11487         queue->decalsequence = cl.decalsequence++;
11488 }
11489
11490 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11491 {
11492         int i;
11493         r_decalsystem_splatqueue_t *queue;
11494
11495         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11496                 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);
11497         r_decalsystem_numqueued = 0;
11498 }
11499
11500 extern cvar_t cl_decals_max;
11501 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11502 {
11503         int i;
11504         decalsystem_t *decalsystem = &ent->decalsystem;
11505         int numdecals;
11506         int killsequence;
11507         tridecal_t *decal;
11508         float frametime;
11509         float lifetime;
11510
11511         if (!decalsystem->numdecals)
11512                 return;
11513
11514         if (r_showsurfaces.integer)
11515                 return;
11516
11517         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11518         {
11519                 R_DecalSystem_Reset(decalsystem);
11520                 return;
11521         }
11522
11523         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11524         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11525
11526         if (decalsystem->lastupdatetime)
11527                 frametime = (cl.time - decalsystem->lastupdatetime);
11528         else
11529                 frametime = 0;
11530         decalsystem->lastupdatetime = cl.time;
11531         decal = decalsystem->decals;
11532         numdecals = decalsystem->numdecals;
11533
11534         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11535         {
11536                 if (decal->color4ub[0][3])
11537                 {
11538                         decal->lived += frametime;
11539                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11540                         {
11541                                 memset(decal, 0, sizeof(*decal));
11542                                 if (decalsystem->freedecal > i)
11543                                         decalsystem->freedecal = i;
11544                         }
11545                 }
11546         }
11547         decal = decalsystem->decals;
11548         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11549                 numdecals--;
11550
11551         // collapse the array by shuffling the tail decals into the gaps
11552         for (;;)
11553         {
11554                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11555                         decalsystem->freedecal++;
11556                 if (decalsystem->freedecal == numdecals)
11557                         break;
11558                 decal[decalsystem->freedecal] = decal[--numdecals];
11559         }
11560
11561         decalsystem->numdecals = numdecals;
11562
11563         if (numdecals <= 0)
11564         {
11565                 // if there are no decals left, reset decalsystem
11566                 R_DecalSystem_Reset(decalsystem);
11567         }
11568 }
11569
11570 extern skinframe_t *decalskinframe;
11571 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11572 {
11573         int i;
11574         decalsystem_t *decalsystem = &ent->decalsystem;
11575         int numdecals;
11576         tridecal_t *decal;
11577         float fadedelay;
11578         float faderate;
11579         float alpha;
11580         float *v3f;
11581         float *c4f;
11582         float *t2f;
11583         const int *e;
11584         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11585         int numtris = 0;
11586
11587         numdecals = decalsystem->numdecals;
11588         if (!numdecals)
11589                 return;
11590
11591         if (r_showsurfaces.integer)
11592                 return;
11593
11594         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11595         {
11596                 R_DecalSystem_Reset(decalsystem);
11597                 return;
11598         }
11599
11600         // if the model is static it doesn't matter what value we give for
11601         // wantnormals and wanttangents, so this logic uses only rules applicable
11602         // to a model, knowing that they are meaningless otherwise
11603         if (ent == r_refdef.scene.worldentity)
11604                 RSurf_ActiveWorldEntity();
11605         else
11606                 RSurf_ActiveModelEntity(ent, false, false, false);
11607
11608         decalsystem->lastupdatetime = cl.time;
11609         decal = decalsystem->decals;
11610
11611         fadedelay = cl_decals_time.value;
11612         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11613
11614         // update vertex positions for animated models
11615         v3f = decalsystem->vertex3f;
11616         c4f = decalsystem->color4f;
11617         t2f = decalsystem->texcoord2f;
11618         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11619         {
11620                 if (!decal->color4ub[0][3])
11621                         continue;
11622
11623                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11624                         continue;
11625
11626                 // update color values for fading decals
11627                 if (decal->lived >= cl_decals_time.value)
11628                 {
11629                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11630                         alpha *= (1.0f/255.0f);
11631                 }
11632                 else
11633                         alpha = 1.0f/255.0f;
11634
11635                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11636                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11637                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11638                 c4f[ 3] = 1;
11639                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11640                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11641                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11642                 c4f[ 7] = 1;
11643                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11644                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11645                 c4f[10] = decal->color4ub[2][2] * alpha;
11646                 c4f[11] = 1;
11647
11648                 t2f[0] = decal->texcoord2f[0][0];
11649                 t2f[1] = decal->texcoord2f[0][1];
11650                 t2f[2] = decal->texcoord2f[1][0];
11651                 t2f[3] = decal->texcoord2f[1][1];
11652                 t2f[4] = decal->texcoord2f[2][0];
11653                 t2f[5] = decal->texcoord2f[2][1];
11654
11655                 // update vertex positions for animated models
11656                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11657                 {
11658                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11659                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11660                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11661                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11662                 }
11663                 else
11664                 {
11665                         VectorCopy(decal->vertex3f[0], v3f);
11666                         VectorCopy(decal->vertex3f[1], v3f + 3);
11667                         VectorCopy(decal->vertex3f[2], v3f + 6);
11668                 }
11669
11670                 v3f += 9;
11671                 c4f += 12;
11672                 t2f += 6;
11673                 numtris++;
11674         }
11675
11676         if (numtris > 0)
11677         {
11678                 r_refdef.stats.drawndecals += numtris;
11679
11680                 if (r_refdef.fogenabled)
11681                 {
11682                         switch(vid.renderpath)
11683                         {
11684                         case RENDERPATH_GL20:
11685                         case RENDERPATH_CGGL:
11686                         case RENDERPATH_GL13:
11687                         case RENDERPATH_GL11:
11688                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11689                                 {
11690                                         alpha = RSurf_FogVertex(v3f);
11691                                         c4f[0] *= alpha;
11692                                         c4f[1] *= alpha;
11693                                         c4f[2] *= alpha;
11694                                 }
11695                                 break;
11696                         }
11697                 }
11698
11699                 // now render the decals all at once
11700                 // (this assumes they all use one particle font texture!)
11701                 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);
11702                 R_Mesh_ResetTextureState();
11703                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11704                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11705                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11706                 GL_DepthMask(false);
11707                 GL_DepthRange(0, 1);
11708                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11709                 GL_DepthTest(true);
11710                 GL_CullFace(GL_NONE);
11711                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11712                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11713                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11714         }
11715 }
11716
11717 static void R_DrawModelDecals(void)
11718 {
11719         int i, numdecals;
11720
11721         // fade faster when there are too many decals
11722         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11723         for (i = 0;i < r_refdef.scene.numentities;i++)
11724                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11725
11726         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11727         for (i = 0;i < r_refdef.scene.numentities;i++)
11728                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11729                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11730
11731         R_DecalSystem_ApplySplatEntitiesQueue();
11732
11733         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11734         for (i = 0;i < r_refdef.scene.numentities;i++)
11735                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11736
11737         r_refdef.stats.totaldecals += numdecals;
11738
11739         if (r_showsurfaces.integer)
11740                 return;
11741
11742         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11743
11744         for (i = 0;i < r_refdef.scene.numentities;i++)
11745         {
11746                 if (!r_refdef.viewcache.entityvisible[i])
11747                         continue;
11748                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11749                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11750         }
11751 }
11752
11753 void R_DrawDebugModel(void)
11754 {
11755         entity_render_t *ent = rsurface.entity;
11756         int i, j, k, l, flagsmask;
11757         const int *elements;
11758         q3mbrush_t *brush;
11759         const msurface_t *surface;
11760         dp_model_t *model = ent->model;
11761         vec3_t v;
11762
11763         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11764
11765         R_Mesh_ColorPointer(NULL, 0, 0);
11766         R_Mesh_ResetTextureState();
11767         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11768         GL_DepthRange(0, 1);
11769         GL_DepthTest(!r_showdisabledepthtest.integer);
11770         GL_DepthMask(false);
11771         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11772
11773         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11774         {
11775                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11776                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11777                 {
11778                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11779                         {
11780                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11781                                 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);
11782                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11783                         }
11784                 }
11785                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11786                 {
11787                         if (surface->num_collisiontriangles)
11788                         {
11789                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11790                                 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);
11791                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11792                         }
11793                 }
11794         }
11795
11796         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11797
11798         if (r_showtris.integer || r_shownormals.integer)
11799         {
11800                 if (r_showdisabledepthtest.integer)
11801                 {
11802                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11803                         GL_DepthMask(false);
11804                 }
11805                 else
11806                 {
11807                         GL_BlendFunc(GL_ONE, GL_ZERO);
11808                         GL_DepthMask(true);
11809                 }
11810                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11811                 {
11812                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11813                                 continue;
11814                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11815                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11816                         {
11817                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11818                                 if (r_showtris.value > 0)
11819                                 {
11820                                         if (!rsurface.texture->currentlayers->depthmask)
11821                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11822                                         else if (ent == r_refdef.scene.worldentity)
11823                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11824                                         else
11825                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11826                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11827                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11828                                         R_Mesh_ColorPointer(NULL, 0, 0);
11829                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11830                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11831                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11832                                         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);
11833                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11834                                         CHECKGLERROR
11835                                 }
11836                                 if (r_shownormals.value < 0)
11837                                 {
11838                                         qglBegin(GL_LINES);
11839                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11840                                         {
11841                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11842                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11843                                                 qglVertex3f(v[0], v[1], v[2]);
11844                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11845                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11846                                                 qglVertex3f(v[0], v[1], v[2]);
11847                                         }
11848                                         qglEnd();
11849                                         CHECKGLERROR
11850                                 }
11851                                 if (r_shownormals.value > 0)
11852                                 {
11853                                         qglBegin(GL_LINES);
11854                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11855                                         {
11856                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11857                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11858                                                 qglVertex3f(v[0], v[1], v[2]);
11859                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11860                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11861                                                 qglVertex3f(v[0], v[1], v[2]);
11862                                         }
11863                                         qglEnd();
11864                                         CHECKGLERROR
11865                                         qglBegin(GL_LINES);
11866                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11867                                         {
11868                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11869                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11870                                                 qglVertex3f(v[0], v[1], v[2]);
11871                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11872                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11873                                                 qglVertex3f(v[0], v[1], v[2]);
11874                                         }
11875                                         qglEnd();
11876                                         CHECKGLERROR
11877                                         qglBegin(GL_LINES);
11878                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11879                                         {
11880                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11881                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11882                                                 qglVertex3f(v[0], v[1], v[2]);
11883                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11884                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11885                                                 qglVertex3f(v[0], v[1], v[2]);
11886                                         }
11887                                         qglEnd();
11888                                         CHECKGLERROR
11889                                 }
11890                         }
11891                 }
11892                 rsurface.texture = NULL;
11893         }
11894 }
11895
11896 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11897 int r_maxsurfacelist = 0;
11898 const msurface_t **r_surfacelist = NULL;
11899 void R_DrawWorldSurfaces(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 = r_refdef.scene.worldmodel;
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         RSurf_ActiveWorldEntity();
11919
11920         surfaces = model->data_surfaces;
11921         update = model->brushq1.lightmapupdateflags;
11922
11923         // update light styles on this submodel
11924         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11925         {
11926                 model_brush_lightstyleinfo_t *style;
11927                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11928                 {
11929                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11930                         {
11931                                 int *list = style->surfacelist;
11932                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11933                                 for (j = 0;j < style->numsurfaces;j++)
11934                                         update[list[j]] = true;
11935                         }
11936                 }
11937         }
11938
11939         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11940
11941         if (debug)
11942         {
11943                 R_DrawDebugModel();
11944                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11945                 return;
11946         }
11947
11948         f = 0;
11949         t = NULL;
11950         rsurface.uselightmaptexture = false;
11951         rsurface.texture = NULL;
11952         rsurface.rtlight = NULL;
11953         numsurfacelist = 0;
11954         // add visible surfaces to draw list
11955         for (i = 0;i < model->nummodelsurfaces;i++)
11956         {
11957                 j = model->sortedmodelsurfaces[i];
11958                 if (r_refdef.viewcache.world_surfacevisible[j])
11959                         r_surfacelist[numsurfacelist++] = surfaces + j;
11960         }
11961         // update lightmaps if needed
11962         if (model->brushq1.firstrender)
11963         {
11964                 model->brushq1.firstrender = false;
11965                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11966                         if (update[j])
11967                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11968         }
11969         else if (update)
11970         {
11971                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11972                         if (r_refdef.viewcache.world_surfacevisible[j])
11973                                 if (update[j])
11974                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11975         }
11976         // don't do anything if there were no surfaces
11977         if (!numsurfacelist)
11978         {
11979                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11980                 return;
11981         }
11982         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11983         GL_AlphaTest(false);
11984
11985         // add to stats if desired
11986         if (r_speeds.integer && !skysurfaces && !depthonly)
11987         {
11988                 r_refdef.stats.world_surfaces += numsurfacelist;
11989                 for (j = 0;j < numsurfacelist;j++)
11990                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11991         }
11992
11993         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11994 }
11995
11996 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11997 {
11998         int i, j, endj, f, flagsmask;
11999         texture_t *t;
12000         dp_model_t *model = ent->model;
12001         msurface_t *surfaces;
12002         unsigned char *update;
12003         int numsurfacelist = 0;
12004         if (model == NULL)
12005                 return;
12006
12007         if (r_maxsurfacelist < model->num_surfaces)
12008         {
12009                 r_maxsurfacelist = model->num_surfaces;
12010                 if (r_surfacelist)
12011                         Mem_Free((msurface_t **)r_surfacelist);
12012                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12013         }
12014
12015         // if the model is static it doesn't matter what value we give for
12016         // wantnormals and wanttangents, so this logic uses only rules applicable
12017         // to a model, knowing that they are meaningless otherwise
12018         if (ent == r_refdef.scene.worldentity)
12019                 RSurf_ActiveWorldEntity();
12020         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12021                 RSurf_ActiveModelEntity(ent, false, false, false);
12022         else if (prepass)
12023                 RSurf_ActiveModelEntity(ent, true, true, true);
12024         else if (depthonly)
12025                 RSurf_ActiveModelEntity(ent, false, false, false);
12026         else
12027         {
12028                 switch (vid.renderpath)
12029                 {
12030                 case RENDERPATH_GL20:
12031                 case RENDERPATH_CGGL:
12032                         RSurf_ActiveModelEntity(ent, true, true, false);
12033                         break;
12034                 case RENDERPATH_GL13:
12035                 case RENDERPATH_GL11:
12036                         RSurf_ActiveModelEntity(ent, true, false, false);
12037                         break;
12038                 }
12039         }
12040
12041         surfaces = model->data_surfaces;
12042         update = model->brushq1.lightmapupdateflags;
12043
12044         // update light styles
12045         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12046         {
12047                 model_brush_lightstyleinfo_t *style;
12048                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12049                 {
12050                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12051                         {
12052                                 int *list = style->surfacelist;
12053                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12054                                 for (j = 0;j < style->numsurfaces;j++)
12055                                         update[list[j]] = true;
12056                         }
12057                 }
12058         }
12059
12060         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12061
12062         if (debug)
12063         {
12064                 R_DrawDebugModel();
12065                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12066                 return;
12067         }
12068
12069         f = 0;
12070         t = NULL;
12071         rsurface.uselightmaptexture = false;
12072         rsurface.texture = NULL;
12073         rsurface.rtlight = NULL;
12074         numsurfacelist = 0;
12075         // add visible surfaces to draw list
12076         for (i = 0;i < model->nummodelsurfaces;i++)
12077                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12078         // don't do anything if there were no surfaces
12079         if (!numsurfacelist)
12080         {
12081                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12082                 return;
12083         }
12084         // update lightmaps if needed
12085         if (update)
12086         {
12087                 int updated = 0;
12088                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12089                 {
12090                         if (update[j])
12091                         {
12092                                 updated++;
12093                                 R_BuildLightMap(ent, surfaces + j);
12094                         }
12095                 }
12096         }
12097         if (update)
12098                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12099                         if (update[j])
12100                                 R_BuildLightMap(ent, surfaces + j);
12101         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12102         GL_AlphaTest(false);
12103
12104         // add to stats if desired
12105         if (r_speeds.integer && !skysurfaces && !depthonly)
12106         {
12107                 r_refdef.stats.entities_surfaces += numsurfacelist;
12108                 for (j = 0;j < numsurfacelist;j++)
12109                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12110         }
12111
12112         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12113 }
12114
12115 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12116 {
12117         static texture_t texture;
12118         static msurface_t surface;
12119         const msurface_t *surfacelist = &surface;
12120
12121         // fake enough texture and surface state to render this geometry
12122
12123         texture.update_lastrenderframe = -1; // regenerate this texture
12124         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12125         texture.currentskinframe = skinframe;
12126         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12127         texture.specularscalemod = 1;
12128         texture.specularpowermod = 1;
12129
12130         surface.texture = &texture;
12131         surface.num_triangles = numtriangles;
12132         surface.num_firsttriangle = firsttriangle;
12133         surface.num_vertices = numvertices;
12134         surface.num_firstvertex = firstvertex;
12135
12136         // now render it
12137         rsurface.texture = R_GetCurrentTexture(surface.texture);
12138         rsurface.uselightmaptexture = false;
12139         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12140 }
12141
12142 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)
12143 {
12144         static msurface_t surface;
12145         const msurface_t *surfacelist = &surface;
12146
12147         // fake enough texture and surface state to render this geometry
12148
12149         surface.texture = texture;
12150         surface.num_triangles = numtriangles;
12151         surface.num_firsttriangle = firsttriangle;
12152         surface.num_vertices = numvertices;
12153         surface.num_firstvertex = firstvertex;
12154
12155         // now render it
12156         rsurface.texture = R_GetCurrentTexture(surface.texture);
12157         rsurface.uselightmaptexture = false;
12158         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12159 }