]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
a8467a3e26c0e3b1bc6f8db2ca4f77a040bf2fc2
[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 "#ifdef MODE_LIGHTSOURCE\n"
844 "varying vec3 LightVector;\n"
845 "#endif\n"
846 "#if defined(MODE_LIGHTDIRECTION)\n"
847 "varying vec3 LightVector;\n"
848 "#endif\n"
849 "\n"
850 "#ifdef USEEYEVECTOR\n"
851 "varying vec3 EyeVector;\n"
852 "#endif\n"
853 "#ifdef USEFOG\n"
854 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
855 "#endif\n"
856 "\n"
857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
858 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
859 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
860 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
861 "#endif\n"
862 "\n"
863 "#ifdef USEREFLECTION\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "#endif\n"
866 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
867 "uniform vec3 LightPosition;\n"
868 "varying vec4 ModelViewPosition;\n"
869 "#endif\n"
870 "\n"
871 "#ifdef MODE_LIGHTSOURCE\n"
872 "uniform vec3 LightPosition;\n"
873 "#endif\n"
874 "uniform vec3 EyePosition;\n"
875 "#ifdef MODE_LIGHTDIRECTION\n"
876 "uniform vec3 LightDir;\n"
877 "#endif\n"
878 "uniform vec4 FogPlane;\n"
879 "\n"
880 "\n"
881 "\n"
882 "\n"
883 "\n"
884 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
885 "\n"
886 "// fragment shader specific:\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "\n"
889 "uniform sampler2D Texture_Normal;\n"
890 "uniform sampler2D Texture_Color;\n"
891 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
892 "uniform sampler2D Texture_Gloss;\n"
893 "//#endif\n"
894 "#ifdef USEGLOW\n"
895 "uniform sampler2D Texture_Glow;\n"
896 "#endif\n"
897 "#ifdef USEVERTEXTEXTUREBLEND\n"
898 "uniform sampler2D Texture_SecondaryNormal;\n"
899 "uniform sampler2D Texture_SecondaryColor;\n"
900 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
901 "uniform sampler2D Texture_SecondaryGloss;\n"
902 "//#endif\n"
903 "#ifdef USEGLOW\n"
904 "uniform sampler2D Texture_SecondaryGlow;\n"
905 "#endif\n"
906 "#endif\n"
907 "#ifdef USECOLORMAPPING\n"
908 "uniform sampler2D Texture_Pants;\n"
909 "uniform sampler2D Texture_Shirt;\n"
910 "#endif\n"
911 "#ifdef USEFOG\n"
912 "uniform sampler2D Texture_FogMask;\n"
913 "#endif\n"
914 "#ifdef USELIGHTMAP\n"
915 "uniform sampler2D Texture_Lightmap;\n"
916 "#endif\n"
917 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
918 "uniform sampler2D Texture_Deluxemap;\n"
919 "#endif\n"
920 "#ifdef USEREFLECTION\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "#endif\n"
923 "\n"
924 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
925 "uniform sampler2DRect Texture_ScreenDepth;\n"
926 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
927 "#endif\n"
928 "#ifdef USEDEFERREDLIGHTMAP\n"
929 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
930 "uniform sampler2DRect Texture_ScreenSpecular;\n"
931 "#endif\n"
932 "\n"
933 "uniform myhalf3 Color_Pants;\n"
934 "uniform myhalf3 Color_Shirt;\n"
935 "uniform myhalf3 FogColor;\n"
936 "\n"
937 "#ifdef USEFOG\n"
938 "uniform float FogRangeRecip;\n"
939 "uniform float FogPlaneViewDist;\n"
940 "uniform float FogHeightFade;\n"
941 "float FogVertex(void)\n"
942 "{\n"
943 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
944 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
945 "       float fogfrac;\n"
946 "#ifdef USEFOGOUTSIDE\n"
947 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
948 "#else\n"
949 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
950 "#endif\n"
951 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
952 "}\n"
953 "#endif\n"
954 "\n"
955 "#ifdef USEOFFSETMAPPING\n"
956 "uniform float OffsetMapping_Scale;\n"
957 "vec2 OffsetMapping(vec2 TexCoord)\n"
958 "{\n"
959 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
960 "       // 14 sample relief mapping: linear search and then binary search\n"
961 "       // this basically steps forward a small amount repeatedly until it finds\n"
962 "       // itself inside solid, then jitters forward and back using decreasing\n"
963 "       // amounts to find the impact\n"
964 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
965 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
966 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
967 "       vec3 RT = vec3(TexCoord, 1);\n"
968 "       OffsetVector *= 0.1;\n"
969 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
970 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
971 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
972 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
973 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
974 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
975 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
976 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
977 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
978 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
979 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
980 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
981 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
982 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
983 "       return RT.xy;\n"
984 "#else\n"
985 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
986 "       // this basically moves forward the full distance, and then backs up based\n"
987 "       // on height of samples\n"
988 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
989 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
990 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
991 "       TexCoord += OffsetVector;\n"
992 "       OffsetVector *= 0.333;\n"
993 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
994 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
995 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
996 "       return TexCoord;\n"
997 "#endif\n"
998 "}\n"
999 "#endif // USEOFFSETMAPPING\n"
1000 "\n"
1001 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1002 "uniform sampler2D Texture_Attenuation;\n"
1003 "uniform samplerCube Texture_Cube;\n"
1004 "\n"
1005 "#ifdef USESHADOWMAPRECT\n"
1006 "# ifdef USESHADOWSAMPLER\n"
1007 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1008 "# else\n"
1009 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1010 "# endif\n"
1011 "#endif\n"
1012 "\n"
1013 "#ifdef USESHADOWMAP2D\n"
1014 "# ifdef USESHADOWSAMPLER\n"
1015 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1016 "# else\n"
1017 "uniform sampler2D Texture_ShadowMap2D;\n"
1018 "# endif\n"
1019 "#endif\n"
1020 "\n"
1021 "#ifdef USESHADOWMAPVSDCT\n"
1022 "uniform samplerCube Texture_CubeProjection;\n"
1023 "#endif\n"
1024 "\n"
1025 "#ifdef USESHADOWMAPCUBE\n"
1026 "# ifdef USESHADOWSAMPLER\n"
1027 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1028 "# else\n"
1029 "uniform samplerCube Texture_ShadowMapCube;\n"
1030 "# endif\n"
1031 "#endif\n"
1032 "\n"
1033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1034 "uniform vec2 ShadowMap_TextureScale;\n"
1035 "uniform vec4 ShadowMap_Parameters;\n"
1036 "#endif\n"
1037 "\n"
1038 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1039 "# ifndef USESHADOWMAPVSDCT\n"
1040 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1041 "{\n"
1042 "       vec3 adir = abs(dir);\n"
1043 "       vec2 tc;\n"
1044 "       vec2 offset;\n"
1045 "       float ma;\n"
1046 "       if (adir.x > adir.y)\n"
1047 "       {\n"
1048 "               if (adir.x > adir.z) // X\n"
1049 "               {\n"
1050 "                       ma = adir.x;\n"
1051 "                       tc = dir.zy;\n"
1052 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1053 "               }\n"
1054 "               else // Z\n"
1055 "               {\n"
1056 "                       ma = adir.z;\n"
1057 "                       tc = dir.xy;\n"
1058 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1059 "               }\n"
1060 "       }\n"
1061 "       else\n"
1062 "       {\n"
1063 "               if (adir.y > adir.z) // Y\n"
1064 "               {\n"
1065 "                       ma = adir.y;\n"
1066 "                       tc = dir.xz;\n"
1067 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1068 "               }\n"
1069 "               else // Z\n"
1070 "               {\n"
1071 "                       ma = adir.z;\n"
1072 "                       tc = dir.xy;\n"
1073 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1074 "               }\n"
1075 "       }\n"
1076 "\n"
1077 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1078 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1079 "       stc.z += ShadowMap_Parameters.z;\n"
1080 "       return stc;\n"
1081 "}\n"
1082 "# else\n"
1083 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1084 "{\n"
1085 "       vec3 adir = abs(dir);\n"
1086 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1087 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1088 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1089 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1090 "       stc.z += ShadowMap_Parameters.z;\n"
1091 "       return stc;\n"
1092 "}\n"
1093 "# endif\n"
1094 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1095 "\n"
1096 "#ifdef USESHADOWMAPCUBE\n"
1097 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1098 "{\n"
1099 "       vec3 adir = abs(dir);\n"
1100 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1101 "}\n"
1102 "#endif\n"
1103 "\n"
1104 "# ifdef USESHADOWMAPRECT\n"
1105 "float ShadowMapCompare(vec3 dir)\n"
1106 "{\n"
1107 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1108 "       float f;\n"
1109 "#  ifdef USESHADOWSAMPLER\n"
1110 "\n"
1111 "#    ifdef USESHADOWMAPPCF\n"
1112 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1113 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1114 "#    else\n"
1115 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1116 "#    endif\n"
1117 "\n"
1118 "#  else\n"
1119 "\n"
1120 "#    ifdef USESHADOWMAPPCF\n"
1121 "#      if USESHADOWMAPPCF > 1\n"
1122 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1123 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1124 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1125 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1126 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1127 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1128 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1129 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1130 "#      else\n"
1131 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1132 "       vec2 offset = fract(shadowmaptc.xy);\n"
1133 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1134 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1135 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1136 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1137 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1138 "#      endif\n"
1139 "#    else\n"
1140 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1141 "#    endif\n"
1142 "\n"
1143 "#  endif\n"
1144 "       return f;\n"
1145 "}\n"
1146 "# endif\n"
1147 "\n"
1148 "# ifdef USESHADOWMAP2D\n"
1149 "float ShadowMapCompare(vec3 dir)\n"
1150 "{\n"
1151 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1152 "       float f;\n"
1153 "\n"
1154 "#  ifdef USESHADOWSAMPLER\n"
1155 "#    ifdef USESHADOWMAPPCF\n"
1156 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1157 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1158 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1159 "#    else\n"
1160 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1161 "#    endif\n"
1162 "#  else\n"
1163 "#    ifdef USESHADOWMAPPCF\n"
1164 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1165 "#      ifdef GL_ARB_texture_gather\n"
1166 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1167 "#      else\n"
1168 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1169 "#      endif\n"
1170 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1171 "       center *= ShadowMap_TextureScale;\n"
1172 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1173 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1174 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1175 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1176 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1177 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1178 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1179 "#     else\n"
1180 "#      ifdef GL_EXT_gpu_shader4\n"
1181 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1182 "#      else\n"
1183 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1184 "#      endif\n"
1185 "#      if USESHADOWMAPPCF > 1\n"
1186 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1187 "       center *= ShadowMap_TextureScale;\n"
1188 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1189 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1190 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1191 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1192 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1193 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1194 "#      else\n"
1195 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1196 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1197 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1198 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1199 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1200 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1201 "#      endif\n"
1202 "#     endif\n"
1203 "#    else\n"
1204 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1205 "#    endif\n"
1206 "#  endif\n"
1207 "       return f;\n"
1208 "}\n"
1209 "# endif\n"
1210 "\n"
1211 "# ifdef USESHADOWMAPCUBE\n"
1212 "float ShadowMapCompare(vec3 dir)\n"
1213 "{\n"
1214 "       // apply depth texture cubemap as light filter\n"
1215 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1216 "       float f;\n"
1217 "#  ifdef USESHADOWSAMPLER\n"
1218 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1219 "#  else\n"
1220 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1221 "#  endif\n"
1222 "       return f;\n"
1223 "}\n"
1224 "# endif\n"
1225 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1226 "#endif // FRAGMENT_SHADER\n"
1227 "\n"
1228 "\n"
1229 "\n"
1230 "\n"
1231 "#ifdef MODE_DEFERREDGEOMETRY\n"
1232 "#ifdef VERTEX_SHADER\n"
1233 "uniform mat4 TexMatrix;\n"
1234 "#ifdef USEVERTEXTEXTUREBLEND\n"
1235 "uniform mat4 BackgroundTexMatrix;\n"
1236 "#endif\n"
1237 "uniform mat4 ModelViewMatrix;\n"
1238 "void main(void)\n"
1239 "{\n"
1240 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1241 "#ifdef USEVERTEXTEXTUREBLEND\n"
1242 "       gl_FrontColor = gl_Color;\n"
1243 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1244 "#endif\n"
1245 "\n"
1246 "       // transform unnormalized eye direction into tangent space\n"
1247 "#ifdef USEOFFSETMAPPING\n"
1248 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1249 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1250 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1251 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1252 "#endif\n"
1253 "\n"
1254 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1255 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1256 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1257 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1258 "}\n"
1259 "#endif // VERTEX_SHADER\n"
1260 "\n"
1261 "#ifdef FRAGMENT_SHADER\n"
1262 "void main(void)\n"
1263 "{\n"
1264 "#ifdef USEOFFSETMAPPING\n"
1265 "       // apply offsetmapping\n"
1266 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1267 "#define TexCoord TexCoordOffset\n"
1268 "#endif\n"
1269 "\n"
1270 "#ifdef USEALPHAKILL\n"
1271 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1272 "               discard;\n"
1273 "#endif\n"
1274 "\n"
1275 "#ifdef USEVERTEXTEXTUREBLEND\n"
1276 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1277 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1278 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1279 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1280 "#endif\n"
1281 "\n"
1282 "#ifdef USEVERTEXTEXTUREBLEND\n"
1283 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1284 "#else\n"
1285 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1286 "#endif\n"
1287 "\n"
1288 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1289 "}\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1292 "\n"
1293 "\n"
1294 "\n"
1295 "\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1299 "void main(void)\n"
1300 "{\n"
1301 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1303 "}\n"
1304 "#endif // VERTEX_SHADER\n"
1305 "\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1315 "#endif\n"
1316 "void main(void)\n"
1317 "{\n"
1318 "       // calculate viewspace pixel position\n"
1319 "       vec3 position;\n"
1320 "       position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1321 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1322 "       // decode viewspace pixel normal\n"
1323 "       myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1324 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1325 "       // surfacenormal = pixel normal in viewspace\n"
1326 "       // LightVector = pixel to light in viewspace\n"
1327 "       // CubeVector = position in lightspace\n"
1328 "       // eyevector = pixel to view in viewspace\n"
1329 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1330 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1331 "#ifdef USEDIFFUSE\n"
1332 "       // calculate diffuse shading\n"
1333 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1334 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1335 "#endif\n"
1336 "#ifdef USESPECULAR\n"
1337 "       // calculate directional shading\n"
1338 "       vec3 eyevector = position * -1.0;\n"
1339 "#  ifdef USEEXACTSPECULARMATH\n"
1340 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1341 "#  else\n"
1342 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1343 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1344 "#  endif\n"
1345 "#endif\n"
1346 "\n"
1347 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1348 "       fade *= ShadowMapCompare(CubeVector);\n"
1349 "#endif\n"
1350 "\n"
1351 "#ifdef USEDIFFUSE\n"
1352 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1353 "#else\n"
1354 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1355 "#endif\n"
1356 "#ifdef USESPECULAR\n"
1357 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1358 "#else\n"
1359 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1360 "#endif\n"
1361 "\n"
1362 "# ifdef USECUBEFILTER\n"
1363 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1364 "       gl_FragData[0] *= cubecolor;\n"
1365 "       gl_FragData[1] *= cubecolor;\n"
1366 "# endif\n"
1367 "}\n"
1368 "#endif // FRAGMENT_SHADER\n"
1369 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1370 "\n"
1371 "\n"
1372 "\n"
1373 "\n"
1374 "#ifdef VERTEX_SHADER\n"
1375 "uniform mat4 TexMatrix;\n"
1376 "#ifdef USEVERTEXTEXTUREBLEND\n"
1377 "uniform mat4 BackgroundTexMatrix;\n"
1378 "#endif\n"
1379 "#ifdef MODE_LIGHTSOURCE\n"
1380 "uniform mat4 ModelToLight;\n"
1381 "#endif\n"
1382 "void main(void)\n"
1383 "{\n"
1384 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1385 "       gl_FrontColor = gl_Color;\n"
1386 "#endif\n"
1387 "       // copy the surface texcoord\n"
1388 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1391 "#endif\n"
1392 "#ifdef USELIGHTMAP\n"
1393 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1394 "#endif\n"
1395 "\n"
1396 "#ifdef MODE_LIGHTSOURCE\n"
1397 "       // transform vertex position into light attenuation/cubemap space\n"
1398 "       // (-1 to +1 across the light box)\n"
1399 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1400 "\n"
1401 "# ifdef USEDIFFUSE\n"
1402 "       // transform unnormalized light direction into tangent space\n"
1403 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1404 "       //  normalize it per pixel)\n"
1405 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1406 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1407 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1408 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1409 "# endif\n"
1410 "#endif\n"
1411 "\n"
1412 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1413 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1414 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1415 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1416 "#endif\n"
1417 "\n"
1418 "       // transform unnormalized eye direction into tangent space\n"
1419 "#ifdef USEEYEVECTOR\n"
1420 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1421 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1422 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1423 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1424 "#endif\n"
1425 "\n"
1426 "#ifdef USEFOG\n"
1427 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1428 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1429 "#endif\n"
1430 "\n"
1431 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1432 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1433 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1434 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1435 "#endif\n"
1436 "\n"
1437 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1438 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1439 "\n"
1440 "#ifdef USEREFLECTION\n"
1441 "       ModelViewProjectionPosition = gl_Position;\n"
1442 "#endif\n"
1443 "}\n"
1444 "#endif // VERTEX_SHADER\n"
1445 "\n"
1446 "\n"
1447 "\n"
1448 "\n"
1449 "#ifdef FRAGMENT_SHADER\n"
1450 "#ifdef USEDEFERREDLIGHTMAP\n"
1451 "uniform myhalf3 DeferredMod_Diffuse;\n"
1452 "uniform myhalf3 DeferredMod_Specular;\n"
1453 "#endif\n"
1454 "uniform myhalf3 Color_Ambient;\n"
1455 "uniform myhalf3 Color_Diffuse;\n"
1456 "uniform myhalf3 Color_Specular;\n"
1457 "uniform myhalf SpecularPower;\n"
1458 "#ifdef USEGLOW\n"
1459 "uniform myhalf3 Color_Glow;\n"
1460 "#endif\n"
1461 "uniform myhalf Alpha;\n"
1462 "#ifdef USEREFLECTION\n"
1463 "uniform vec4 DistortScaleRefractReflect;\n"
1464 "uniform vec4 ScreenScaleRefractReflect;\n"
1465 "uniform vec4 ScreenCenterRefractReflect;\n"
1466 "uniform myhalf4 ReflectColor;\n"
1467 "#endif\n"
1468 "#ifdef MODE_LIGHTDIRECTION\n"
1469 "uniform myhalf3 LightColor;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTSOURCE\n"
1472 "uniform myhalf3 LightColor;\n"
1473 "#endif\n"
1474 "void main(void)\n"
1475 "{\n"
1476 "#ifdef USEOFFSETMAPPING\n"
1477 "       // apply offsetmapping\n"
1478 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1479 "#define TexCoord TexCoordOffset\n"
1480 "#endif\n"
1481 "\n"
1482 "       // combine the diffuse textures (base, pants, shirt)\n"
1483 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1484 "#ifdef USEALPHAKILL\n"
1485 "       if (color.a < 0.5)\n"
1486 "               discard;\n"
1487 "#endif\n"
1488 "       color.a *= Alpha;\n"
1489 "#ifdef USECOLORMAPPING\n"
1490 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1491 "#endif\n"
1492 "#ifdef USEVERTEXTEXTUREBLEND\n"
1493 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1494 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1495 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1496 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1497 "       color.a = 1.0;\n"
1498 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1499 "#endif\n"
1500 "\n"
1501 "       // get the surface normal\n"
1502 "#ifdef USEVERTEXTEXTUREBLEND\n"
1503 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1504 "#else\n"
1505 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1506 "#endif\n"
1507 "\n"
1508 "       // get the material colors\n"
1509 "       myhalf3 diffusetex = color.rgb;\n"
1510 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1511 "# ifdef USEVERTEXTEXTUREBLEND\n"
1512 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1513 "# else\n"
1514 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1515 "# endif\n"
1516 "#endif\n"
1517 "\n"
1518 "\n"
1519 "\n"
1520 "\n"
1521 "#ifdef MODE_LIGHTSOURCE\n"
1522 "       // light source\n"
1523 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1524 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1525 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1526 "#ifdef USESPECULAR\n"
1527 "#ifdef USEEXACTSPECULARMATH\n"
1528 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1529 "#else\n"
1530 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1531 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1532 "#endif\n"
1533 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1534 "#endif\n"
1535 "       color.rgb *= LightColor;\n"
1536 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1537 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1538 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1539 "#endif\n"
1540 "# ifdef USECUBEFILTER\n"
1541 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1542 "# endif\n"
1543 "#endif // MODE_LIGHTSOURCE\n"
1544 "\n"
1545 "\n"
1546 "\n"
1547 "\n"
1548 "#ifdef MODE_LIGHTDIRECTION\n"
1549 "#define SHADING\n"
1550 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1551 "#define lightcolor LightColor\n"
1552 "#endif // MODE_LIGHTDIRECTION\n"
1553 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1554 "#define SHADING\n"
1555 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1556 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1557 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1558 "       // convert modelspace light vector to tangentspace\n"
1559 "       myhalf3 lightnormal;\n"
1560 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1561 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1562 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1563 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1564 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1565 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1566 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1567 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1568 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1569 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1570 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1571 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1572 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1573 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1574 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1575 "#define SHADING\n"
1576 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1577 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1578 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1579 "#endif\n"
1580 "\n"
1581 "\n"
1582 "\n"
1583 "\n"
1584 "#ifdef MODE_LIGHTMAP\n"
1585 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1586 "#endif // MODE_LIGHTMAP\n"
1587 "#ifdef MODE_VERTEXCOLOR\n"
1588 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1589 "#endif // MODE_VERTEXCOLOR\n"
1590 "#ifdef MODE_FLATCOLOR\n"
1591 "       color.rgb = diffusetex * Color_Ambient;\n"
1592 "#endif // MODE_FLATCOLOR\n"
1593 "\n"
1594 "\n"
1595 "\n"
1596 "\n"
1597 "#ifdef SHADING\n"
1598 "# ifdef USEDIFFUSE\n"
1599 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1600 "#  ifdef USESPECULAR\n"
1601 "#   ifdef USEEXACTSPECULARMATH\n"
1602 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1603 "#   else\n"
1604 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1605 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1606 "#   endif\n"
1607 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1608 "#  else\n"
1609 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1610 "#  endif\n"
1611 "# else\n"
1612 "       color.rgb = diffusetex * Color_Ambient;\n"
1613 "# endif\n"
1614 "#endif\n"
1615 "\n"
1616 "#ifdef USEDEFERREDLIGHTMAP\n"
1617 "       color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1618 "       color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1619 "#endif\n"
1620 "\n"
1621 "#ifdef USEGLOW\n"
1622 "#ifdef USEVERTEXTEXTUREBLEND\n"
1623 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1624 "#else\n"
1625 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1626 "#endif\n"
1627 "#endif\n"
1628 "\n"
1629 "#ifdef USEFOG\n"
1630 "#ifdef MODE_LIGHTSOURCE\n"
1631 "       color.rgb *= myhalf(FogVertex());\n"
1632 "#else\n"
1633 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1634 "#endif\n"
1635 "#endif\n"
1636 "\n"
1637 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1638 "#ifdef USEREFLECTION\n"
1639 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1640 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1641 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1642 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1643 "       // FIXME temporary hack to detect the case that the reflection\n"
1644 "       // gets blackened at edges due to leaving the area that contains actual\n"
1645 "       // content.\n"
1646 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1647 "       // 'appening.\n"
1648 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1649 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1650 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1651 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1652 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1653 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1654 "#endif\n"
1655 "\n"
1656 "       gl_FragColor = vec4(color);\n"
1657 "}\n"
1658 "#endif // FRAGMENT_SHADER\n"
1659 "\n"
1660 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1661 "#endif // !MODE_DEFERREDGEOMETRY\n"
1662 "#endif // !MODE_WATER\n"
1663 "#endif // !MODE_REFRACTION\n"
1664 "#endif // !MODE_BLOOMBLUR\n"
1665 "#endif // !MODE_GENERIC\n"
1666 "#endif // !MODE_POSTPROCESS\n"
1667 "#endif // !MODE_SHOWDEPTH\n"
1668 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1669 ;
1670
1671 /*
1672 =========================================================================================================================================================
1673
1674
1675
1676 =========================================================================================================================================================
1677
1678
1679
1680 =========================================================================================================================================================
1681
1682
1683
1684 =========================================================================================================================================================
1685
1686
1687
1688 =========================================================================================================================================================
1689
1690
1691
1692 =========================================================================================================================================================
1693
1694
1695
1696 =========================================================================================================================================================
1697 */
1698
1699 const char *builtincgshaderstring =
1700 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1701 "// written by Forest 'LordHavoc' Hale\n"
1702 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1703 "\n"
1704 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1705 "# define USEFOG\n"
1706 "#endif\n"
1707 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1708 "#define USELIGHTMAP\n"
1709 "#endif\n"
1710 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1711 "#define USEEYEVECTOR\n"
1712 "#endif\n"
1713 "\n"
1714 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1715 "#ifdef VERTEX_SHADER\n"
1716 "void main\n"
1717 "(\n"
1718 "float4 gl_Vertex : POSITION,\n"
1719 "uniform float4x4 ModelViewProjectionMatrix,\n"
1720 "out float4 gl_Position : POSITION\n"
1721 ")\n"
1722 "{\n"
1723 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1724 "}\n"
1725 "#endif\n"
1726 "#else // !MODE_DEPTH_ORSHADOW\n"
1727 "\n"
1728 "\n"
1729 "\n"
1730 "\n"
1731 "#ifdef MODE_SHOWDEPTH\n"
1732 "#ifdef VERTEX_SHADER\n"
1733 "void main\n"
1734 "(\n"
1735 "float4 gl_Vertex : POSITION,\n"
1736 "uniform float4x4 ModelViewProjectionMatrix,\n"
1737 "out float4 gl_Position : POSITION,\n"
1738 "out float4 gl_FrontColor : COLOR0\n"
1739 ")\n"
1740 "{\n"
1741 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1742 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1743 "}\n"
1744 "#endif\n"
1745 "\n"
1746 "#ifdef FRAGMENT_SHADER\n"
1747 "void main\n"
1748 "(\n"
1749 "float4 gl_FrontColor : COLOR0,\n"
1750 "out float4 gl_FragColor : COLOR\n"
1751 ")\n"
1752 "{\n"
1753 "       gl_FragColor = gl_FrontColor;\n"
1754 "}\n"
1755 "#endif\n"
1756 "#else // !MODE_SHOWDEPTH\n"
1757 "\n"
1758 "\n"
1759 "\n"
1760 "\n"
1761 "#ifdef MODE_POSTPROCESS\n"
1762 "\n"
1763 "#ifdef VERTEX_SHADER\n"
1764 "void main\n"
1765 "(\n"
1766 "float4 gl_Vertex : POSITION,\n"
1767 "uniform float4x4 ModelViewProjectionMatrix,\n"
1768 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1769 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1770 "out float4 gl_Position : POSITION,\n"
1771 "out float2 TexCoord1 : TEXCOORD0,\n"
1772 "out float2 TexCoord2 : TEXCOORD1\n"
1773 ")\n"
1774 "{\n"
1775 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1776 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1777 "#ifdef USEBLOOM\n"
1778 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1779 "#endif\n"
1780 "}\n"
1781 "#endif\n"
1782 "\n"
1783 "#ifdef FRAGMENT_SHADER\n"
1784 "void main\n"
1785 "(\n"
1786 "float2 TexCoord1 : TEXCOORD0,\n"
1787 "float2 TexCoord2 : TEXCOORD1,\n"
1788 "uniform sampler2D Texture_First,\n"
1789 "#ifdef USEBLOOM\n"
1790 "uniform sampler2D Texture_Second,\n"
1791 "#endif\n"
1792 "#ifdef USEGAMMARAMPS\n"
1793 "uniform sampler2D Texture_GammaRamps,\n"
1794 "#endif\n"
1795 "#ifdef USESATURATION\n"
1796 "uniform float Saturation,\n"
1797 "#endif\n"
1798 "#ifdef USEVIEWTINT\n"
1799 "uniform float4 ViewTintColor,\n"
1800 "#endif\n"
1801 "uniform float4 UserVec1,\n"
1802 "uniform float4 UserVec2,\n"
1803 "uniform float4 UserVec3,\n"
1804 "uniform float4 UserVec4,\n"
1805 "uniform float ClientTime,\n"
1806 "uniform float2 PixelSize,\n"
1807 "out float4 gl_FragColor : COLOR\n"
1808 ")\n"
1809 "{\n"
1810 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1811 "#ifdef USEBLOOM\n"
1812 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1813 "#endif\n"
1814 "#ifdef USEVIEWTINT\n"
1815 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1816 "#endif\n"
1817 "\n"
1818 "#ifdef USEPOSTPROCESSING\n"
1819 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1820 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1821 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1822 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1823 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1824 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1825 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1826 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1827 "#endif\n"
1828 "\n"
1829 "#ifdef USESATURATION\n"
1830 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1831 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1832 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1833 "       gl_FragColor.rgb = mix(float3(y), gl_FragColor.rgb, Saturation);\n"
1834 "#endif\n"
1835 "\n"
1836 "#ifdef USEGAMMARAMPS\n"
1837 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1838 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1839 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1840 "#endif\n"
1841 "}\n"
1842 "#endif\n"
1843 "#else // !MODE_POSTPROCESS\n"
1844 "\n"
1845 "\n"
1846 "\n"
1847 "\n"
1848 "#ifdef MODE_GENERIC\n"
1849 "#ifdef VERTEX_SHADER\n"
1850 "void main\n"
1851 "(\n"
1852 "float4 gl_Vertex : POSITION,\n"
1853 "uniform float4x4 ModelViewProjectionMatrix,\n"
1854 "float4 gl_Color : COLOR0,\n"
1855 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1856 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1857 "out float4 gl_Position : POSITION,\n"
1858 "out float4 gl_FrontColor : COLOR,\n"
1859 "out float2 TexCoord1 : TEXCOORD0,\n"
1860 "out float2 TexCoord2 : TEXCOORD1\n"
1861 ")\n"
1862 "{\n"
1863 "       gl_FrontColor = gl_Color;\n"
1864 "#ifdef USEDIFFUSE\n"
1865 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1866 "#endif\n"
1867 "#ifdef USESPECULAR\n"
1868 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1869 "#endif\n"
1870 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1871 "}\n"
1872 "#endif\n"
1873 "\n"
1874 "#ifdef FRAGMENT_SHADER\n"
1875 "\n"
1876 "void main\n"
1877 "(\n"
1878 "float4 gl_FrontColor : COLOR,\n"
1879 "float2 TexCoord1 : TEXCOORD0,\n"
1880 "float2 TexCoord2 : TEXCOORD1,\n"
1881 "#ifdef USEDIFFUSE\n"
1882 "uniform sampler2D Texture_First,\n"
1883 "#endif\n"
1884 "#ifdef USESPECULAR\n"
1885 "uniform sampler2D Texture_Second,\n"
1886 "#endif\n"
1887 "out float4 gl_FragColor : COLOR\n"
1888 ")\n"
1889 "{\n"
1890 "       gl_FragColor = gl_FrontColor;\n"
1891 "#ifdef USEDIFFUSE\n"
1892 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1893 "#endif\n"
1894 "\n"
1895 "#ifdef USESPECULAR\n"
1896 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1897 "# ifdef USECOLORMAPPING\n"
1898 "       gl_FragColor *= tex2;\n"
1899 "# endif\n"
1900 "# ifdef USEGLOW\n"
1901 "       gl_FragColor += tex2;\n"
1902 "# endif\n"
1903 "# ifdef USEVERTEXTEXTUREBLEND\n"
1904 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
1905 "# endif\n"
1906 "#endif\n"
1907 "}\n"
1908 "#endif\n"
1909 "#else // !MODE_GENERIC\n"
1910 "\n"
1911 "\n"
1912 "\n"
1913 "\n"
1914 "#ifdef MODE_BLOOMBLUR\n"
1915 "#ifdef VERTEX_SHADER\n"
1916 "void main\n"
1917 "(\n"
1918 "float4 gl_Vertex : POSITION,\n"
1919 "uniform float4x4 ModelViewProjectionMatrix,\n"
1920 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1921 "out float4 gl_Position : POSITION,\n"
1922 "out float2 TexCoord : TEXCOORD0\n"
1923 ")\n"
1924 "{\n"
1925 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1926 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1927 "}\n"
1928 "#endif\n"
1929 "\n"
1930 "#ifdef FRAGMENT_SHADER\n"
1931 "\n"
1932 "void main\n"
1933 "(\n"
1934 "float2 TexCoord : TEXCOORD0,\n"
1935 "uniform sampler2D Texture_First,\n"
1936 "uniform float4 BloomBlur_Parameters,\n"
1937 "out float4 gl_FragColor : COLOR\n"
1938 ")\n"
1939 "{\n"
1940 "       int i;\n"
1941 "       float2 tc = TexCoord;\n"
1942 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1943 "       tc += BloomBlur_Parameters.xy;\n"
1944 "       for (i = 1;i < SAMPLES;i++)\n"
1945 "       {\n"
1946 "               color += tex2D(Texture_First, tc).rgb;\n"
1947 "               tc += BloomBlur_Parameters.xy;\n"
1948 "       }\n"
1949 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1950 "}\n"
1951 "#endif\n"
1952 "#else // !MODE_BLOOMBLUR\n"
1953 "#ifdef MODE_REFRACTION\n"
1954 "#ifdef VERTEX_SHADER\n"
1955 "void main\n"
1956 "(\n"
1957 "float4 gl_Vertex : POSITION,\n"
1958 "uniform float4x4 ModelViewProjectionMatrix,\n"
1959 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1960 "uniform mat4 TexMatrix,\n"
1961 "uniform float3 EyePosition,\n"
1962 "out float4 gl_Position : POSITION,\n"
1963 "out float2 TexCoord : TEXCOORD0,\n"
1964 "out float3 EyeVector : TEXCOORD1,\n"
1965 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1966 ")\n"
1967 "{\n"
1968 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1969 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1970 "       ModelViewProjectionPosition = gl_Position;\n"
1971 "}\n"
1972 "#endif\n"
1973 "\n"
1974 "#ifdef FRAGMENT_SHADER\n"
1975 "void main\n"
1976 "(\n"
1977 "float2 TexCoord : TEXCOORD0,\n"
1978 "float3 EyeVector : TEXCOORD1,\n"
1979 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1980 "uniform sampler2D Texture_Normal,\n"
1981 "uniform sampler2D Texture_Refraction,\n"
1982 "uniform sampler2D Texture_Reflection,\n"
1983 "uniform float4 DistortScaleRefractReflect,\n"
1984 "uniform float4 ScreenScaleRefractReflect,\n"
1985 "uniform float4 ScreenCenterRefractReflect,\n"
1986 "uniform float4 RefractColor,\n"
1987 "out float4 gl_FragColor : COLOR\n"
1988 ")\n"
1989 "{\n"
1990 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1991 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1992 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1993 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1994 "       // FIXME temporary hack to detect the case that the reflection\n"
1995 "       // gets blackened at edges due to leaving the area that contains actual\n"
1996 "       // content.\n"
1997 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1998 "       // 'appening.\n"
1999 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2000 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2001 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2002 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2003 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2004 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2005 "}\n"
2006 "#endif\n"
2007 "#else // !MODE_REFRACTION\n"
2008 "\n"
2009 "\n"
2010 "\n"
2011 "\n"
2012 "#ifdef MODE_WATER\n"
2013 "#ifdef VERTEX_SHADER\n"
2014 "\n"
2015 "void main\n"
2016 "(\n"
2017 "float4 gl_Vertex : POSITION,\n"
2018 "uniform float4x4 ModelViewProjectionMatrix,\n"
2019 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2020 "uniform mat4 TexMatrix,\n"
2021 "uniform float3 EyePosition,\n"
2022 "out float4 gl_Position : POSITION,\n"
2023 "out float2 TexCoord : TEXCOORD0,\n"
2024 "out float3 EyeVector : TEXCOORD1,\n"
2025 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2026 ")\n"
2027 "{\n"
2028 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2029 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2030 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2031 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2032 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2033 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2034 "       ModelViewProjectionPosition = gl_Position;\n"
2035 "}\n"
2036 "#endif\n"
2037 "\n"
2038 "#ifdef FRAGMENT_SHADER\n"
2039 "void main\n"
2040 "(\n"
2041 "float2 TexCoord : TEXCOORD0,\n"
2042 "float3 EyeVector : TEXCOORD1,\n"
2043 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2044 "uniform sampler2D Texture_Normal,\n"
2045 "uniform sampler2D Texture_Refraction,\n"
2046 "uniform sampler2D Texture_Reflection,\n"
2047 "uniform float4 DistortScaleRefractReflect,\n"
2048 "uniform float4 ScreenScaleRefractReflect,\n"
2049 "uniform float4 ScreenCenterRefractReflect,\n"
2050 "uniform float4 RefractColor,\n"
2051 "uniform float4 ReflectColor,\n"
2052 "uniform float ReflectFactor,\n"
2053 "uniform float ReflectOffset,\n"
2054 "out float4 gl_FragColor : COLOR\n"
2055 ")\n"
2056 "{\n"
2057 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2058 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2059 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2060 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2061 "       // FIXME temporary hack to detect the case that the reflection\n"
2062 "       // gets blackened at edges due to leaving the area that contains actual\n"
2063 "       // content.\n"
2064 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2065 "       // 'appening.\n"
2066 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2067 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2068 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2069 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2070 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2071 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2072 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2073 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2074 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2075 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2076 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2077 "       gl_FragColor = mix(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2078 "}\n"
2079 "#endif\n"
2080 "#else // !MODE_WATER\n"
2081 "\n"
2082 "\n"
2083 "\n"
2084 "\n"
2085 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2086 "\n"
2087 "// fragment shader specific:\n"
2088 "#ifdef FRAGMENT_SHADER\n"
2089 "\n"
2090 "#ifdef USEFOG\n"
2091 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2092 "{\n"
2093 "       float fogfrac;\n"
2094 "#ifdef USEFOGOUTSIDE\n"
2095 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2096 "#else\n"
2097 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2098 "#endif\n"
2099 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2100 "}\n"
2101 "#endif\n"
2102 "\n"
2103 "#ifdef USEOFFSETMAPPING\n"
2104 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2105 "{\n"
2106 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2107 "       // 14 sample relief mapping: linear search and then binary search\n"
2108 "       // this basically steps forward a small amount repeatedly until it finds\n"
2109 "       // itself inside solid, then jitters forward and back using decreasing\n"
2110 "       // amounts to find the impact\n"
2111 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2112 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2113 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2114 "       float3 RT = float3(TexCoord, 1);\n"
2115 "       OffsetVector *= 0.1;\n"
2116 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2117 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2118 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2119 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2120 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2121 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2122 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2123 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2124 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2125 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2126 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2127 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2128 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2129 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2130 "       return RT.xy;\n"
2131 "#else\n"
2132 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2133 "       // this basically moves forward the full distance, and then backs up based\n"
2134 "       // on height of samples\n"
2135 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2136 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2137 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2138 "       TexCoord += OffsetVector;\n"
2139 "       OffsetVector *= 0.333;\n"
2140 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2141 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2142 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2143 "       return TexCoord;\n"
2144 "#endif\n"
2145 "}\n"
2146 "#endif // USEOFFSETMAPPING\n"
2147 "\n"
2148 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2149 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2150 "# ifndef USESHADOWMAPVSDCT\n"
2151 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2152 "{\n"
2153 "       float3 adir = abs(dir);\n"
2154 "       float2 tc;\n"
2155 "       float2 offset;\n"
2156 "       float ma;\n"
2157 "       if (adir.x > adir.y)\n"
2158 "       {\n"
2159 "               if (adir.x > adir.z) // X\n"
2160 "               {\n"
2161 "                       ma = adir.x;\n"
2162 "                       tc = dir.zy;\n"
2163 "                       offset = float2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2164 "               }\n"
2165 "               else // Z\n"
2166 "               {\n"
2167 "                       ma = adir.z;\n"
2168 "                       tc = dir.xy;\n"
2169 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2170 "               }\n"
2171 "       }\n"
2172 "       else\n"
2173 "       {\n"
2174 "               if (adir.y > adir.z) // Y\n"
2175 "               {\n"
2176 "                       ma = adir.y;\n"
2177 "                       tc = dir.xz;\n"
2178 "                       offset = float2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2179 "               }\n"
2180 "               else // Z\n"
2181 "               {\n"
2182 "                       ma = adir.z;\n"
2183 "                       tc = dir.xy;\n"
2184 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2185 "               }\n"
2186 "       }\n"
2187 "\n"
2188 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2189 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2190 "       stc.z += ShadowMap_Parameters.z;\n"
2191 "       return stc;\n"
2192 "}\n"
2193 "# else\n"
2194 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2195 "{\n"
2196 "       float3 adir = abs(dir);\n"
2197 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2198 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2199 "       float3 stc = float3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2200 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2201 "       stc.z += ShadowMap_Parameters.z;\n"
2202 "       return stc;\n"
2203 "}\n"
2204 "# endif\n"
2205 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2206 "\n"
2207 "#ifdef USESHADOWMAPCUBE\n"
2208 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2209 "{\n"
2210 "    float3 adir = abs(dir);\n"
2211 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2212 "}\n"
2213 "#endif\n"
2214 "\n"
2215 "# ifdef USESHADOWMAPRECT\n"
2216 "#ifdef USESHADOWMAPVSDCT\n"
2217 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2218 "#else\n"
2219 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2220 "#endif\n"
2221 "{\n"
2222 "#ifdef USESHADOWMAPVSDCT\n"
2223 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2224 "#else\n"
2225 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2226 "#endif\n"
2227 "       float f;\n"
2228 "#  ifdef USESHADOWSAMPLER\n"
2229 "\n"
2230 "#    ifdef USESHADOWMAPPCF\n"
2231 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2232 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2233 "#    else\n"
2234 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2235 "#    endif\n"
2236 "\n"
2237 "#  else\n"
2238 "\n"
2239 "#    ifdef USESHADOWMAPPCF\n"
2240 "#      if USESHADOWMAPPCF > 1\n"
2241 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2242 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2243 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2244 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2245 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2246 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2247 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2248 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2249 "#      else\n"
2250 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2251 "    float2 offset = fract(shadowmaptc.xy);\n"
2252 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2253 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2254 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2255 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2256 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2257 "#      endif\n"
2258 "#    else\n"
2259 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2260 "#    endif\n"
2261 "\n"
2262 "#  endif\n"
2263 "       return f;\n"
2264 "}\n"
2265 "# endif\n"
2266 "\n"
2267 "# ifdef USESHADOWMAP2D\n"
2268 "#ifdef USESHADOWMAPVSDCT\n"
2269 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2270 "#else\n"
2271 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2272 "#endif\n"
2273 "{\n"
2274 "#ifdef USESHADOWMAPVSDCT\n"
2275 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2276 "#else\n"
2277 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2278 "#endif\n"
2279 "    float f;\n"
2280 "\n"
2281 "#  ifdef USESHADOWSAMPLER\n"
2282 "#    ifdef USESHADOWMAPPCF\n"
2283 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2284 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2285 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2286 "#    else\n"
2287 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2288 "#    endif\n"
2289 "#  else\n"
2290 "#    ifdef USESHADOWMAPPCF\n"
2291 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2292 "#      ifdef GL_ARB_texture_gather\n"
2293 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2294 "#      else\n"
2295 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2296 "#      endif\n"
2297 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2298 "    center *= ShadowMap_TextureScale;\n"
2299 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2300 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2301 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2302 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2303 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2304 "                mix(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2305 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2306 "#     else\n"
2307 "#      ifdef GL_EXT_gpu_shader4\n"
2308 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, ifloat2(x, y)).r\n"
2309 "#      else\n"
2310 "#        define texval(x, y) tex2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2311 "#      endif\n"
2312 "#      if USESHADOWMAPPCF > 1\n"
2313 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2314 "    center *= ShadowMap_TextureScale;\n"
2315 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2316 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2317 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2318 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2319 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2320 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2321 "#      else\n"
2322 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
2323 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2324 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2325 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2326 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2327 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2328 "#      endif\n"
2329 "#     endif\n"
2330 "#    else\n"
2331 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2332 "#    endif\n"
2333 "#  endif\n"
2334 "    return f;\n"
2335 "}\n"
2336 "# endif\n"
2337 "\n"
2338 "# ifdef USESHADOWMAPCUBE\n"
2339 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2340 "{\n"
2341 "    // apply depth texture cubemap as light filter\n"
2342 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2343 "    float f;\n"
2344 "#  ifdef USESHADOWSAMPLER\n"
2345 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2346 "#  else\n"
2347 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2348 "#  endif\n"
2349 "    return f;\n"
2350 "}\n"
2351 "# endif\n"
2352 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2353 "#endif // FRAGMENT_SHADER\n"
2354 "\n"
2355 "\n"
2356 "\n"
2357 "\n"
2358 "#ifdef MODE_DEFERREDGEOMETRY\n"
2359 "#ifdef VERTEX_SHADER\n"
2360 "void main\n"
2361 "(\n"
2362 "float4 gl_Vertex : POSITION,\n"
2363 "uniform float4x4 ModelViewProjectionMatrix,\n"
2364 "#ifdef USEVERTEXTEXTUREBLEND\n"
2365 "float4 gl_Color : COLOR0,\n"
2366 "#endif\n"
2367 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2368 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2369 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2370 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2371 "uniform mat4 TexMatrix,\n"
2372 "#ifdef USEVERTEXTEXTUREBLEND\n"
2373 "uniform mat4 BackgroundTexMatrix,\n"
2374 "#endif\n"
2375 "uniform mat4 ModelViewMatrix,\n"
2376 "out float4 gl_Position : POSITION,\n"
2377 "out float4 gl_FrontColor : COLOR,\n"
2378 "out float4 TexCoordBoth : TEXCOORD0,\n"
2379 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2380 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2381 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2382 ")\n"
2383 "{\n"
2384 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2385 "#ifdef USEVERTEXTEXTUREBLEND\n"
2386 "       gl_FrontColor = gl_Color;\n"
2387 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2388 "#endif\n"
2389 "\n"
2390 "       // transform unnormalized eye direction into tangent space\n"
2391 "#ifdef USEOFFSETMAPPING\n"
2392 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2393 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2394 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2395 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2396 "#endif\n"
2397 "\n"
2398 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2399 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2400 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2401 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2402 "}\n"
2403 "#endif // VERTEX_SHADER\n"
2404 "\n"
2405 "#ifdef FRAGMENT_SHADER\n"
2406 "void main\n"
2407 "(\n"
2408 "float4 TexCoordBoth : TEXCOORD0,\n"
2409 "float3 EyeVector : TEXCOORD2,\n"
2410 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2411 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2412 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2413 "uniform sampler2D Texture_Normal,\n"
2414 "#ifdef USEALPHAKILL\n"
2415 "uniform sampler2D Texture_Color,\n"
2416 "#endif\n"
2417 "#ifdef USEVERTEXTEXTUREBLEND\n"
2418 "uniform sampler2D Texture_SecondaryNormal,\n"
2419 "#endif\n"
2420 "#ifdef USEOFFSETMAPPING\n"
2421 "uniform float OffsetMapping_Scale,\n"
2422 "#endif\n"
2423 "uniform half SpecularPower,\n"
2424 "out float4 gl_FragColor : COLOR\n"
2425 ")\n"
2426 "{\n"
2427 "       float2 TexCoord = TexCoordBoth.xy;\n"
2428 "#ifdef USEOFFSETMAPPING\n"
2429 "       // apply offsetmapping\n"
2430 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2431 "#define TexCoord TexCoordOffset\n"
2432 "#endif\n"
2433 "\n"
2434 "#ifdef USEALPHAKILL\n"
2435 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2436 "               discard;\n"
2437 "#endif\n"
2438 "\n"
2439 "#ifdef USEVERTEXTEXTUREBLEND\n"
2440 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2441 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2442 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2443 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2444 "#endif\n"
2445 "\n"
2446 "#ifdef USEVERTEXTEXTUREBLEND\n"
2447 "       float3 surfacenormal = mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2448 "#else\n"
2449 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2450 "#endif\n"
2451 "\n"
2452 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2453 "}\n"
2454 "#endif // FRAGMENT_SHADER\n"
2455 "#else // !MODE_DEFERREDGEOMETRY\n"
2456 "\n"
2457 "\n"
2458 "\n"
2459 "\n"
2460 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2461 "#ifdef VERTEX_SHADER\n"
2462 "void main\n"
2463 "(\n"
2464 "float4 gl_Vertex : POSITION,\n"
2465 "uniform float4x4 ModelViewProjectionMatrix,\n"
2466 "uniform mat4 ModelViewMatrix,\n"
2467 "out float4 gl_Position : POSITION,\n"
2468 "out float4 ModelViewPosition : TEXCOORD0\n"
2469 ")\n"
2470 "{\n"
2471 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2472 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2473 "}\n"
2474 "#endif // VERTEX_SHADER\n"
2475 "\n"
2476 "#ifdef FRAGMENT_SHADER\n"
2477 "void main\n"
2478 "(\n"
2479 "float2 Pixel : WPOS,\n"
2480 "float4 ModelViewPosition : TEXCOORD0,\n"
2481 "uniform mat4 ViewToLight,\n"
2482 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2483 "uniform float3 LightPosition,\n"
2484 "uniform half3 DeferredColor_Ambient,\n"
2485 "uniform half3 DeferredColor_Diffuse,\n"
2486 "#ifdef USESPECULAR\n"
2487 "uniform half3 DeferredColor_Specular,\n"
2488 "uniform half SpecularPower,\n"
2489 "#endif\n"
2490 "uniform sampler2D Texture_Attenuation,\n"
2491 "uniform samplerRECT Texture_ScreenDepth,\n"
2492 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2493 "\n"
2494 "#ifdef USESHADOWMAPRECT\n"
2495 "# ifdef USESHADOWSAMPLER\n"
2496 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2497 "# else\n"
2498 "uniform samplerRECT Texture_ShadowMapRect,\n"
2499 "# endif\n"
2500 "#endif\n"
2501 "\n"
2502 "#ifdef USESHADOWMAP2D\n"
2503 "# ifdef USESHADOWSAMPLER\n"
2504 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2505 "# else\n"
2506 "uniform sampler2D Texture_ShadowMap2D,\n"
2507 "# endif\n"
2508 "#endif\n"
2509 "\n"
2510 "#ifdef USESHADOWMAPVSDCT\n"
2511 "uniform samplerCUBE Texture_CubeProjection,\n"
2512 "#endif\n"
2513 "\n"
2514 "#ifdef USESHADOWMAPCUBE\n"
2515 "# ifdef USESHADOWSAMPLER\n"
2516 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2517 "# else\n"
2518 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2519 "# endif\n"
2520 "#endif\n"
2521 "\n"
2522 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2523 "uniform float2 ShadowMap_TextureScale,\n"
2524 "uniform float4 ShadowMap_Parameters,\n"
2525 "#endif\n"
2526 "\n"
2527 "out float4 gl_FragData0 : COLOR0,\n"
2528 "out float4 gl_FragData1 : COLOR1\n"
2529 ")\n"
2530 "{\n"
2531 "       // calculate viewspace pixel position\n"
2532 "       float3 position;\n"
2533 "       position.z = ScreenToDepth.y / (texRECT(Texture_ScreenDepth, Pixel).r + ScreenToDepth.x);\n"
2534 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2535 "       // decode viewspace pixel normal\n"
2536 "       half4 normalmap = texRECT(Texture_ScreenNormalMap, Pixel);\n"
2537 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2538 "       // surfacenormal = pixel normal in viewspace\n"
2539 "       // LightVector = pixel to light in viewspace\n"
2540 "       // CubeVector = position in lightspace\n"
2541 "       // eyevector = pixel to view in viewspace\n"
2542 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2543 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2544 "#ifdef USEDIFFUSE\n"
2545 "       // calculate diffuse shading\n"
2546 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2547 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2548 "#endif\n"
2549 "#ifdef USESPECULAR\n"
2550 "       // calculate directional shading\n"
2551 "       float3 eyevector = position * -1.0;\n"
2552 "#  ifdef USEEXACTSPECULARMATH\n"
2553 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2554 "#  else\n"
2555 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2556 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2557 "#  endif\n"
2558 "#endif\n"
2559 "\n"
2560 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2561 "       fade *= ShadowMapCompare(CubeVector,\n"
2562 "# if defined(USESHADOWMAP2D)\n"
2563 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2564 "# endif\n"
2565 "# if defined(USESHADOWMAPRECT)\n"
2566 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2567 "# endif\n"
2568 "# if defined(USESHADOWMAPCUBE)\n"
2569 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2570 "# endif\n"
2571 "\n"
2572 "#ifdef USESHADOWMAPVSDCT\n"
2573 ", Texture_CubeProjection\n"
2574 "#endif\n"
2575 "       );\n"
2576 "#endif\n"
2577 "\n"
2578 "#ifdef USEDIFFUSE\n"
2579 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2580 "#else\n"
2581 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2582 "#endif\n"
2583 "#ifdef USESPECULAR\n"
2584 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2585 "#else\n"
2586 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2587 "#endif\n"
2588 "\n"
2589 "# ifdef USECUBEFILTER\n"
2590 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2591 "       gl_FragData0.rgb *= cubecolor;\n"
2592 "       gl_FragData1.rgb *= cubecolor;\n"
2593 "# endif\n"
2594 "}\n"
2595 "#endif // FRAGMENT_SHADER\n"
2596 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2597 "\n"
2598 "\n"
2599 "\n"
2600 "\n"
2601 "#ifdef VERTEX_SHADER\n"
2602 "void main\n"
2603 "(\n"
2604 "float4 gl_Vertex : POSITION,\n"
2605 "uniform float4x4 ModelViewProjectionMatrix,\n"
2606 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2607 "float4 gl_Color : COLOR0,\n"
2608 "#endif\n"
2609 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2610 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2611 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2612 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2613 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2614 "\n"
2615 "uniform float3 EyePosition,\n"
2616 "uniform mat4 TexMatrix,\n"
2617 "#ifdef USEVERTEXTEXTUREBLEND\n"
2618 "uniform mat4 BackgroundTexMatrix,\n"
2619 "#endif\n"
2620 "#ifdef MODE_LIGHTSOURCE\n"
2621 "uniform mat4 ModelToLight,\n"
2622 "#endif\n"
2623 "#ifdef MODE_LIGHTSOURCE\n"
2624 "uniform float3 LightPosition,\n"
2625 "#endif\n"
2626 "#ifdef MODE_LIGHTDIRECTION\n"
2627 "uniform float3 LightDir,\n"
2628 "#endif\n"
2629 "uniform float4 FogPlane,\n"
2630 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2631 "uniform float3 LightPosition,\n"
2632 "#endif\n"
2633 "\n"
2634 "out float4 gl_FrontColor : COLOR,\n"
2635 "out float4 TexCoordBoth : TEXCOORD0,\n"
2636 "#ifdef USELIGHTMAP\n"
2637 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2638 "#endif\n"
2639 "#ifdef USEEYEVECTOR\n"
2640 "out float3 EyeVector : TEXCOORD2,\n"
2641 "#endif\n"
2642 "#ifdef USEREFLECTION\n"
2643 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2644 "#endif\n"
2645 "#ifdef USEFOG\n"
2646 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2647 "#endif\n"
2648 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2649 "out float3 LightVector : TEXCOORD5,\n"
2650 "#endif\n"
2651 "#ifdef MODE_LIGHTSOURCE\n"
2652 "out float3 CubeVector : TEXCOORD3,\n"
2653 "#endif\n"
2654 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2655 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2656 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2657 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2658 "#endif\n"
2659 "out float4 gl_Position : POSITION\n"
2660 ")\n"
2661 "{\n"
2662 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2663 "       gl_FrontColor = gl_Color;\n"
2664 "#endif\n"
2665 "       // copy the surface texcoord\n"
2666 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2667 "#ifdef USEVERTEXTEXTUREBLEND\n"
2668 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2669 "#endif\n"
2670 "#ifdef USELIGHTMAP\n"
2671 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2672 "#endif\n"
2673 "\n"
2674 "#ifdef MODE_LIGHTSOURCE\n"
2675 "       // transform vertex position into light attenuation/cubemap space\n"
2676 "       // (-1 to +1 across the light box)\n"
2677 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2678 "\n"
2679 "# ifdef USEDIFFUSE\n"
2680 "       // transform unnormalized light direction into tangent space\n"
2681 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2682 "       //  normalize it per pixel)\n"
2683 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2684 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2685 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2686 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2687 "# endif\n"
2688 "#endif\n"
2689 "\n"
2690 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2691 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2692 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2693 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2694 "#endif\n"
2695 "\n"
2696 "       // transform unnormalized eye direction into tangent space\n"
2697 "#ifdef USEEYEVECTOR\n"
2698 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2699 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2700 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2701 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2702 "#endif\n"
2703 "\n"
2704 "#ifdef USEFOG\n"
2705 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2706 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2710 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2711 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2712 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2713 "#endif\n"
2714 "\n"
2715 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2716 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2717 "\n"
2718 "#ifdef USEREFLECTION\n"
2719 "       ModelViewProjectionPosition = gl_Position;\n"
2720 "#endif\n"
2721 "}\n"
2722 "#endif // VERTEX_SHADER\n"
2723 "\n"
2724 "\n"
2725 "\n"
2726 "\n"
2727 "#ifdef FRAGMENT_SHADER\n"
2728 "void main\n"
2729 "(\n"
2730 "#ifdef USEDEFERREDLIGHTMAP\n"
2731 "float2 Pixel : WPOS,\n"
2732 "#endif\n"
2733 "float4 gl_FrontColor : COLOR,\n"
2734 "float4 TexCoordBoth : TEXCOORD0,\n"
2735 "#ifdef USELIGHTMAP\n"
2736 "float2 TexCoordLightmap : TEXCOORD1,\n"
2737 "#endif\n"
2738 "#ifdef USEEYEVECTOR\n"
2739 "float3 EyeVector : TEXCOORD2,\n"
2740 "#endif\n"
2741 "#ifdef USEREFLECTION\n"
2742 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2743 "#endif\n"
2744 "#ifdef USEFOG\n"
2745 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2746 "#endif\n"
2747 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2748 "float3 LightVector : TEXCOORD5,\n"
2749 "#endif\n"
2750 "#ifdef MODE_LIGHTSOURCE\n"
2751 "float3 CubeVector : TEXCOORD3,\n"
2752 "#endif\n"
2753 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2754 "float4 ModelViewPosition : TEXCOORD0,\n"
2755 "#endif\n"
2756 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2757 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2758 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2759 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2760 "#endif\n"
2761 "\n"
2762 "uniform sampler2D Texture_Normal,\n"
2763 "uniform sampler2D Texture_Color,\n"
2764 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2765 "uniform sampler2D Texture_Gloss,\n"
2766 "#endif\n"
2767 "#ifdef USEGLOW\n"
2768 "uniform sampler2D Texture_Glow,\n"
2769 "#endif\n"
2770 "#ifdef USEVERTEXTEXTUREBLEND\n"
2771 "uniform sampler2D Texture_SecondaryNormal,\n"
2772 "uniform sampler2D Texture_SecondaryColor,\n"
2773 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2774 "uniform sampler2D Texture_SecondaryGloss,\n"
2775 "#endif\n"
2776 "#ifdef USEGLOW\n"
2777 "uniform sampler2D Texture_SecondaryGlow,\n"
2778 "#endif\n"
2779 "#endif\n"
2780 "#ifdef USECOLORMAPPING\n"
2781 "uniform sampler2D Texture_Pants,\n"
2782 "uniform sampler2D Texture_Shirt,\n"
2783 "#endif\n"
2784 "#ifdef USEFOG\n"
2785 "uniform sampler2D Texture_FogMask,\n"
2786 "#endif\n"
2787 "#ifdef USELIGHTMAP\n"
2788 "uniform sampler2D Texture_Lightmap,\n"
2789 "#endif\n"
2790 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2791 "uniform sampler2D Texture_Deluxemap,\n"
2792 "#endif\n"
2793 "#ifdef USEREFLECTION\n"
2794 "uniform sampler2D Texture_Reflection,\n"
2795 "#endif\n"
2796 "\n"
2797 "//#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2798 "uniform samplerRECT Texture_ScreenDepth,\n"
2799 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2800 "//#endif\n"
2801 "#ifdef USEDEFERREDLIGHTMAP\n"
2802 "uniform samplerRECT Texture_ScreenDiffuse,\n"
2803 "uniform samplerRECT Texture_ScreenSpecular,\n"
2804 "#endif\n"
2805 "\n"
2806 "#ifdef USECOLORMAPPING\n"
2807 "uniform half3 Color_Pants,\n"
2808 "uniform half3 Color_Shirt,\n"
2809 "#endif\n"
2810 "#ifdef USEFOG\n"
2811 "uniform float3 FogColor,\n"
2812 "uniform float FogRangeRecip,\n"
2813 "uniform float FogPlaneViewDist,\n"
2814 "uniform float FogHeightFade,\n"
2815 "#endif\n"
2816 "\n"
2817 "#ifdef USEOFFSETMAPPING\n"
2818 "uniform float OffsetMapping_Scale,\n"
2819 "#endif\n"
2820 "\n"
2821 "#ifdef USEDEFERREDLIGHTMAP\n"
2822 "uniform half3 DeferredMod_Diffuse,\n"
2823 "uniform half3 DeferredMod_Specular,\n"
2824 "#endif\n"
2825 "uniform half3 Color_Ambient,\n"
2826 "uniform half3 Color_Diffuse,\n"
2827 "uniform half3 Color_Specular,\n"
2828 "uniform half SpecularPower,\n"
2829 "#ifdef USEGLOW\n"
2830 "uniform half3 Color_Glow,\n"
2831 "#endif\n"
2832 "uniform half Alpha,\n"
2833 "#ifdef USEREFLECTION\n"
2834 "uniform float4 DistortScaleRefractReflect,\n"
2835 "uniform float4 ScreenScaleRefractReflect,\n"
2836 "uniform float4 ScreenCenterRefractReflect,\n"
2837 "uniform half4 ReflectColor,\n"
2838 "#endif\n"
2839 "#ifdef MODE_LIGHTDIRECTION\n"
2840 "uniform half3 LightColor,\n"
2841 "#endif\n"
2842 "#ifdef MODE_LIGHTSOURCE\n"
2843 "uniform half3 LightColor,\n"
2844 "#endif\n"
2845 "\n"
2846 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2847 "uniform sampler2D Texture_Attenuation,\n"
2848 "uniform samplerCUBE Texture_Cube,\n"
2849 "\n"
2850 "#ifdef USESHADOWMAPRECT\n"
2851 "# ifdef USESHADOWSAMPLER\n"
2852 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2853 "# else\n"
2854 "uniform samplerRECT Texture_ShadowMapRect,\n"
2855 "# endif\n"
2856 "#endif\n"
2857 "\n"
2858 "#ifdef USESHADOWMAP2D\n"
2859 "# ifdef USESHADOWSAMPLER\n"
2860 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2861 "# else\n"
2862 "uniform sampler2D Texture_ShadowMap2D,\n"
2863 "# endif\n"
2864 "#endif\n"
2865 "\n"
2866 "#ifdef USESHADOWMAPVSDCT\n"
2867 "uniform samplerCUBE Texture_CubeProjection,\n"
2868 "#endif\n"
2869 "\n"
2870 "#ifdef USESHADOWMAPCUBE\n"
2871 "# ifdef USESHADOWSAMPLER\n"
2872 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2873 "# else\n"
2874 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2875 "# endif\n"
2876 "#endif\n"
2877 "\n"
2878 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2879 "uniform float2 ShadowMap_TextureScale,\n"
2880 "uniform float4 ShadowMap_Parameters,\n"
2881 "#endif\n"
2882 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2883 "\n"
2884 "out float4 gl_FragColor : COLOR\n"
2885 ")\n"
2886 "{\n"
2887 "       float2 TexCoord = TexCoordBoth.xy;\n"
2888 "#ifdef USEVERTEXTEXTUREBLEND\n"
2889 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2890 "#endif\n"
2891 "#ifdef USEOFFSETMAPPING\n"
2892 "       // apply offsetmapping\n"
2893 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2894 "#define TexCoord TexCoordOffset\n"
2895 "#endif\n"
2896 "\n"
2897 "       // combine the diffuse textures (base, pants, shirt)\n"
2898 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2899 "#ifdef USEALPHAKILL\n"
2900 "       if (color.a < 0.5)\n"
2901 "               discard;\n"
2902 "#endif\n"
2903 "       color.a *= Alpha;\n"
2904 "#ifdef USECOLORMAPPING\n"
2905 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2906 "#endif\n"
2907 "#ifdef USEVERTEXTEXTUREBLEND\n"
2908 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2909 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2910 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2911 "       color.rgb = half3(mix(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2912 "       color.a = 1.0;\n"
2913 "       //color = mix(half4(1, 0, 0, 1), color, terrainblend);\n"
2914 "#endif\n"
2915 "\n"
2916 "       // get the surface normal\n"
2917 "#ifdef USEVERTEXTEXTUREBLEND\n"
2918 "       half3 surfacenormal = normalize(half3(mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2919 "#else\n"
2920 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2921 "#endif\n"
2922 "\n"
2923 "       // get the material colors\n"
2924 "       half3 diffusetex = color.rgb;\n"
2925 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2926 "# ifdef USEVERTEXTEXTUREBLEND\n"
2927 "       half3 glosstex = half3(mix(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2928 "# else\n"
2929 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2930 "# endif\n"
2931 "#endif\n"
2932 "\n"
2933 "\n"
2934 "\n"
2935 "\n"
2936 "#ifdef MODE_LIGHTSOURCE\n"
2937 "       // light source\n"
2938 "       half3 lightnormal = half3(normalize(LightVector));\n"
2939 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2940 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2941 "#ifdef USESPECULAR\n"
2942 "#ifdef USEEXACTSPECULARMATH\n"
2943 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2944 "#else\n"
2945 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2946 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2947 "#endif\n"
2948 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2949 "#endif\n"
2950 "       color.rgb *= LightColor;\n"
2951 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2952 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2953 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2954 "# if defined(USESHADOWMAP2D)\n"
2955 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2956 "# endif\n"
2957 "# if defined(USESHADOWMAPRECT)\n"
2958 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2959 "# endif\n"
2960 "# if defined(USESHADOWMAPCUBE)\n"
2961 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2962 "# endif\n"
2963 "\n"
2964 "#ifdef USESHADOWMAPVSDCT\n"
2965 ", Texture_CubeProjection\n"
2966 "#endif\n"
2967 "       );\n"
2968 "\n"
2969 "#endif\n"
2970 "# ifdef USECUBEFILTER\n"
2971 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2972 "# endif\n"
2973 "#endif // MODE_LIGHTSOURCE\n"
2974 "\n"
2975 "\n"
2976 "\n"
2977 "\n"
2978 "#ifdef MODE_LIGHTDIRECTION\n"
2979 "#define SHADING\n"
2980 "       half3 lightnormal = half3(normalize(LightVector));\n"
2981 "#define lightcolor LightColor\n"
2982 "#endif // MODE_LIGHTDIRECTION\n"
2983 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2984 "#define SHADING\n"
2985 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
2986 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
2987 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
2988 "       // convert modelspace light vector to tangentspace\n"
2989 "       half3 lightnormal;\n"
2990 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
2991 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
2992 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
2993 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
2994 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
2995 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
2996 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
2997 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
2998 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
2999 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3000 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3001 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3002 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3003 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3004 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3005 "#define SHADING\n"
3006 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3007 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3008 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3009 "#endif\n"
3010 "\n"
3011 "\n"
3012 "\n"
3013 "\n"
3014 "#ifdef MODE_LIGHTMAP\n"
3015 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3016 "#endif // MODE_LIGHTMAP\n"
3017 "#ifdef MODE_VERTEXCOLOR\n"
3018 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3019 "#endif // MODE_VERTEXCOLOR\n"
3020 "#ifdef MODE_FLATCOLOR\n"
3021 "       color.rgb = diffusetex * Color_Ambient;\n"
3022 "#endif // MODE_FLATCOLOR\n"
3023 "\n"
3024 "\n"
3025 "\n"
3026 "\n"
3027 "#ifdef SHADING\n"
3028 "# ifdef USEDIFFUSE\n"
3029 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3030 "#  ifdef USESPECULAR\n"
3031 "#   ifdef USEEXACTSPECULARMATH\n"
3032 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3033 "#   else\n"
3034 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3035 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3036 "#   endif\n"
3037 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3038 "#  else\n"
3039 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3040 "#  endif\n"
3041 "# else\n"
3042 "       color.rgb = diffusetex * Color_Ambient;\n"
3043 "# endif\n"
3044 "#endif\n"
3045 "\n"
3046 "#ifdef USEDEFERREDLIGHTMAP\n"
3047 "       color.rgb += diffusetex * half3(texRECT(Texture_ScreenDiffuse, Pixel)) * DeferredMod_Diffuse;\n"
3048 "       color.rgb += glosstex * half3(texRECT(Texture_ScreenSpecular, Pixel)) * DeferredMod_Specular;\n"
3049 "       color.rgb = half3(texRECT(Texture_ScreenDepth, Pixel));\n"
3050 "#endif\n"
3051 "\n"
3052 "#ifdef USEGLOW\n"
3053 "#ifdef USEVERTEXTEXTUREBLEND\n"
3054 "       color.rgb += mix(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3055 "#else\n"
3056 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3057 "#endif\n"
3058 "#endif\n"
3059 "\n"
3060 "#ifdef USEFOG\n"
3061 "#ifdef MODE_LIGHTSOURCE\n"
3062 "       color.rgb *= half(FogVertex());\n"
3063 "#else\n"
3064 "       color.rgb = mix(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3065 "#endif\n"
3066 "#endif\n"
3067 "\n"
3068 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3069 "#ifdef USEREFLECTION\n"
3070 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3071 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3072 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3073 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3074 "       // FIXME temporary hack to detect the case that the reflection\n"
3075 "       // gets blackened at edges due to leaving the area that contains actual\n"
3076 "       // content.\n"
3077 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3078 "       // 'appening.\n"
3079 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3080 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3081 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3082 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3083 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3084 "       color.rgb = mix(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3085 "#endif\n"
3086 "\n"
3087 "       gl_FragColor = float4(color);\n"
3088 "}\n"
3089 "#endif // FRAGMENT_SHADER\n"
3090 "\n"
3091 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3092 "#endif // !MODE_DEFERREDGEOMETRY\n"
3093 "#endif // !MODE_WATER\n"
3094 "#endif // !MODE_REFRACTION\n"
3095 "#endif // !MODE_BLOOMBLUR\n"
3096 "#endif // !MODE_GENERIC\n"
3097 "#endif // !MODE_POSTPROCESS\n"
3098 "#endif // !MODE_SHOWDEPTH\n"
3099 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3100 ;
3101
3102 //=======================================================================================================================================================
3103
3104 typedef struct shaderpermutationinfo_s
3105 {
3106         const char *pretext;
3107         const char *name;
3108 }
3109 shaderpermutationinfo_t;
3110
3111 typedef struct shadermodeinfo_s
3112 {
3113         const char *vertexfilename;
3114         const char *geometryfilename;
3115         const char *fragmentfilename;
3116         const char *pretext;
3117         const char *name;
3118 }
3119 shadermodeinfo_t;
3120
3121 typedef enum shaderpermutation_e
3122 {
3123         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3124         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3125         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3126         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3127         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3128         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3129         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3130         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3131         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3132         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3133         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3134         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3135         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3136         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3137         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3138         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3139         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3140         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3141         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3142         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3143         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3144         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3145         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3146         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3147         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3148         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3149         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3150         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3151 }
3152 shaderpermutation_t;
3153
3154 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3155 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3156 {
3157         {"#define USEDIFFUSE\n", " diffuse"},
3158         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3159         {"#define USEVIEWTINT\n", " viewtint"},
3160         {"#define USECOLORMAPPING\n", " colormapping"},
3161         {"#define USESATURATION\n", " saturation"},
3162         {"#define USEFOGINSIDE\n", " foginside"},
3163         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3164         {"#define USEGAMMARAMPS\n", " gammaramps"},
3165         {"#define USECUBEFILTER\n", " cubefilter"},
3166         {"#define USEGLOW\n", " glow"},
3167         {"#define USEBLOOM\n", " bloom"},
3168         {"#define USESPECULAR\n", " specular"},
3169         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3170         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3171         {"#define USEREFLECTION\n", " reflection"},
3172         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3173         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3174         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3175         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3176         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3177         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3178         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3179         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3180         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3181         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3182         {"#define USEALPHAKILL\n", " alphakill"},
3183 };
3184
3185 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3186 typedef enum shadermode_e
3187 {
3188         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3189         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3190         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3191         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3192         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3193         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3194         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3195         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3196         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3197         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3198         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3199         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3200         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3201         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3202         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3203         SHADERMODE_COUNT
3204 }
3205 shadermode_t;
3206
3207 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3208 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3209 {
3210         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3211         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3212         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3213         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3214         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3215         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3216         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3217         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3218         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3219         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3220         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3221         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3222         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3223         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3224         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3225 };
3226
3227 #ifdef SUPPORTCG
3228 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3229 {
3230         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3231         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3232         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3233         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3234         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3235         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3236         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3237         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3238         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3239         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3240         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3241         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3242         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3243         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3244         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3245 };
3246 #endif
3247
3248 struct r_glsl_permutation_s;
3249 typedef struct r_glsl_permutation_s
3250 {
3251         /// hash lookup data
3252         struct r_glsl_permutation_s *hashnext;
3253         unsigned int mode;
3254         unsigned int permutation;
3255
3256         /// indicates if we have tried compiling this permutation already
3257         qboolean compiled;
3258         /// 0 if compilation failed
3259         int program;
3260         /// locations of detected uniforms in program object, or -1 if not found
3261         int loc_Texture_First;
3262         int loc_Texture_Second;
3263         int loc_Texture_GammaRamps;
3264         int loc_Texture_Normal;
3265         int loc_Texture_Color;
3266         int loc_Texture_Gloss;
3267         int loc_Texture_Glow;
3268         int loc_Texture_SecondaryNormal;
3269         int loc_Texture_SecondaryColor;
3270         int loc_Texture_SecondaryGloss;
3271         int loc_Texture_SecondaryGlow;
3272         int loc_Texture_Pants;
3273         int loc_Texture_Shirt;
3274         int loc_Texture_FogMask;
3275         int loc_Texture_Lightmap;
3276         int loc_Texture_Deluxemap;
3277         int loc_Texture_Attenuation;
3278         int loc_Texture_Cube;
3279         int loc_Texture_Refraction;
3280         int loc_Texture_Reflection;
3281         int loc_Texture_ShadowMapRect;
3282         int loc_Texture_ShadowMapCube;
3283         int loc_Texture_ShadowMap2D;
3284         int loc_Texture_CubeProjection;
3285         int loc_Texture_ScreenDepth;
3286         int loc_Texture_ScreenNormalMap;
3287         int loc_Texture_ScreenDiffuse;
3288         int loc_Texture_ScreenSpecular;
3289         int loc_Alpha;
3290         int loc_BloomBlur_Parameters;
3291         int loc_ClientTime;
3292         int loc_Color_Ambient;
3293         int loc_Color_Diffuse;
3294         int loc_Color_Specular;
3295         int loc_Color_Glow;
3296         int loc_Color_Pants;
3297         int loc_Color_Shirt;
3298         int loc_DeferredColor_Ambient;
3299         int loc_DeferredColor_Diffuse;
3300         int loc_DeferredColor_Specular;
3301         int loc_DeferredMod_Diffuse;
3302         int loc_DeferredMod_Specular;
3303         int loc_DistortScaleRefractReflect;
3304         int loc_EyePosition;
3305         int loc_FogColor;
3306         int loc_FogHeightFade;
3307         int loc_FogPlane;
3308         int loc_FogPlaneViewDist;
3309         int loc_FogRangeRecip;
3310         int loc_LightColor;
3311         int loc_LightDir;
3312         int loc_LightPosition;
3313         int loc_OffsetMapping_Scale;
3314         int loc_PixelSize;
3315         int loc_ReflectColor;
3316         int loc_ReflectFactor;
3317         int loc_ReflectOffset;
3318         int loc_RefractColor;
3319         int loc_Saturation;
3320         int loc_ScreenCenterRefractReflect;
3321         int loc_ScreenScaleRefractReflect;
3322         int loc_ScreenToDepth;
3323         int loc_ShadowMap_Parameters;
3324         int loc_ShadowMap_TextureScale;
3325         int loc_SpecularPower;
3326         int loc_UserVec1;
3327         int loc_UserVec2;
3328         int loc_UserVec3;
3329         int loc_UserVec4;
3330         int loc_ViewTintColor;
3331         int loc_ViewToLight;
3332         int loc_ModelToLight;
3333         int loc_TexMatrix;
3334         int loc_BackgroundTexMatrix;
3335         int loc_ModelViewProjectionMatrix;
3336         int loc_ModelViewMatrix;
3337 }
3338 r_glsl_permutation_t;
3339
3340 #define SHADERPERMUTATION_HASHSIZE 256
3341
3342 /// information about each possible shader permutation
3343 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3344 /// currently selected permutation
3345 r_glsl_permutation_t *r_glsl_permutation;
3346 /// storage for permutations linked in the hash table
3347 memexpandablearray_t r_glsl_permutationarray;
3348
3349 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3350 {
3351         //unsigned int hashdepth = 0;
3352         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3353         r_glsl_permutation_t *p;
3354         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3355         {
3356                 if (p->mode == mode && p->permutation == permutation)
3357                 {
3358                         //if (hashdepth > 10)
3359                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3360                         return p;
3361                 }
3362                 //hashdepth++;
3363         }
3364         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3365         p->mode = mode;
3366         p->permutation = permutation;
3367         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3368         r_glsl_permutationhash[mode][hashindex] = p;
3369         //if (hashdepth > 10)
3370         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3371         return p;
3372 }
3373
3374 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3375 {
3376         char *shaderstring;
3377         if (!filename || !filename[0])
3378                 return NULL;
3379         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3380         if (shaderstring)
3381         {
3382                 if (printfromdisknotice)
3383                         Con_DPrintf("from disk %s... ", filename);
3384                 return shaderstring;
3385         }
3386         else if (!strcmp(filename, "glsl/default.glsl"))
3387         {
3388                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3389                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3390         }
3391         return shaderstring;
3392 }
3393
3394 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3395 {
3396         int i;
3397         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3398         int vertstrings_count = 0;
3399         int geomstrings_count = 0;
3400         int fragstrings_count = 0;
3401         char *vertexstring, *geometrystring, *fragmentstring;
3402         const char *vertstrings_list[32+3];
3403         const char *geomstrings_list[32+3];
3404         const char *fragstrings_list[32+3];
3405         char permutationname[256];
3406
3407         if (p->compiled)
3408                 return;
3409         p->compiled = true;
3410         p->program = 0;
3411
3412         permutationname[0] = 0;
3413         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3414         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3415         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3416
3417         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3418
3419         // the first pretext is which type of shader to compile as
3420         // (later these will all be bound together as a program object)
3421         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3422         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3423         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3424
3425         // the second pretext is the mode (for example a light source)
3426         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3427         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3428         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3429         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3430
3431         // now add all the permutation pretexts
3432         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3433         {
3434                 if (permutation & (1<<i))
3435                 {
3436                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3437                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3438                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3439                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3440                 }
3441                 else
3442                 {
3443                         // keep line numbers correct
3444                         vertstrings_list[vertstrings_count++] = "\n";
3445                         geomstrings_list[geomstrings_count++] = "\n";
3446                         fragstrings_list[fragstrings_count++] = "\n";
3447                 }
3448         }
3449
3450         // now append the shader text itself
3451         vertstrings_list[vertstrings_count++] = vertexstring;
3452         geomstrings_list[geomstrings_count++] = geometrystring;
3453         fragstrings_list[fragstrings_count++] = fragmentstring;
3454
3455         // if any sources were NULL, clear the respective list
3456         if (!vertexstring)
3457                 vertstrings_count = 0;
3458         if (!geometrystring)
3459                 geomstrings_count = 0;
3460         if (!fragmentstring)
3461                 fragstrings_count = 0;
3462
3463         // compile the shader program
3464         if (vertstrings_count + geomstrings_count + fragstrings_count)
3465                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3466         if (p->program)
3467         {
3468                 CHECKGLERROR
3469                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3470                 // look up all the uniform variable names we care about, so we don't
3471                 // have to look them up every time we set them
3472
3473                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3474                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3475                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3476                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3477                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3478                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3479                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3480                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3481                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3482                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3483                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3484                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3485                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3486                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3487                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3488                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3489                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3490                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3491                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3492                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3493                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3494                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3495                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3496                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3497                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3498                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3499                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3500                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3501                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3502                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3503                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3504                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3505                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3506                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3507                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3508                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3509                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3510                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3511                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3512                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3513                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3514                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3515                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3516                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3517                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3518                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3519                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3520                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3521                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3522                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3523                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3524                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3525                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3526                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3527                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3528                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3529                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3530                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3531                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3532                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3533                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3534                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3535                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3536                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3537                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3538                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3539                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3540                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3541                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3542                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3543                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3544                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3545                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3546                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3547                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3548                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3549                 // initialize the samplers to refer to the texture units we use
3550                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3551                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3552                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3553                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3554                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3555                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3556                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3557                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3558                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3559                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3560                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3561                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3562                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3563                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3564                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3565                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3566                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3567                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3568                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3569                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3570                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3571                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3572                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3573                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3574                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3575                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3576                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3577                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3578                 CHECKGLERROR
3579                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3580         }
3581         else
3582                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3583
3584         // free the strings
3585         if (vertexstring)
3586                 Mem_Free(vertexstring);
3587         if (geometrystring)
3588                 Mem_Free(geometrystring);
3589         if (fragmentstring)
3590                 Mem_Free(fragmentstring);
3591 }
3592
3593 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3594 {
3595         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3596         if (r_glsl_permutation != perm)
3597         {
3598                 r_glsl_permutation = perm;
3599                 if (!r_glsl_permutation->program)
3600                 {
3601                         if (!r_glsl_permutation->compiled)
3602                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3603                         if (!r_glsl_permutation->program)
3604                         {
3605                                 // remove features until we find a valid permutation
3606                                 int i;
3607                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3608                                 {
3609                                         // reduce i more quickly whenever it would not remove any bits
3610                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3611                                         if (!(permutation & j))
3612                                                 continue;
3613                                         permutation -= j;
3614                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3615                                         if (!r_glsl_permutation->compiled)
3616                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3617                                         if (r_glsl_permutation->program)
3618                                                 break;
3619                                 }
3620                                 if (i >= SHADERPERMUTATION_COUNT)
3621                                 {
3622                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3623                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3624                                         qglUseProgramObjectARB(0);CHECKGLERROR
3625                                         return; // no bit left to clear, entire mode is broken
3626                                 }
3627                         }
3628                 }
3629                 CHECKGLERROR
3630                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3631         }
3632         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3633         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3634 }
3635
3636 #ifdef SUPPORTCG
3637 #include <Cg/cgGL.h>
3638 struct r_cg_permutation_s;
3639 typedef struct r_cg_permutation_s
3640 {
3641         /// hash lookup data
3642         struct r_cg_permutation_s *hashnext;
3643         unsigned int mode;
3644         unsigned int permutation;
3645
3646         /// indicates if we have tried compiling this permutation already
3647         qboolean compiled;
3648         /// 0 if compilation failed
3649         CGprogram vprogram;
3650         CGprogram fprogram;
3651         /// locations of detected parameters in programs, or NULL if not found
3652         CGparameter vp_EyePosition;
3653         CGparameter vp_FogPlane;
3654         CGparameter vp_LightDir;
3655         CGparameter vp_LightPosition;
3656         CGparameter vp_ModelToLight;
3657         CGparameter vp_TexMatrix;
3658         CGparameter vp_BackgroundTexMatrix;
3659         CGparameter vp_ModelViewProjectionMatrix;
3660         CGparameter vp_ModelViewMatrix;
3661
3662         CGparameter fp_Texture_First;
3663         CGparameter fp_Texture_Second;
3664         CGparameter fp_Texture_GammaRamps;
3665         CGparameter fp_Texture_Normal;
3666         CGparameter fp_Texture_Color;
3667         CGparameter fp_Texture_Gloss;
3668         CGparameter fp_Texture_Glow;
3669         CGparameter fp_Texture_SecondaryNormal;
3670         CGparameter fp_Texture_SecondaryColor;
3671         CGparameter fp_Texture_SecondaryGloss;
3672         CGparameter fp_Texture_SecondaryGlow;
3673         CGparameter fp_Texture_Pants;
3674         CGparameter fp_Texture_Shirt;
3675         CGparameter fp_Texture_FogMask;
3676         CGparameter fp_Texture_Lightmap;
3677         CGparameter fp_Texture_Deluxemap;
3678         CGparameter fp_Texture_Attenuation;
3679         CGparameter fp_Texture_Cube;
3680         CGparameter fp_Texture_Refraction;
3681         CGparameter fp_Texture_Reflection;
3682         CGparameter fp_Texture_ShadowMapRect;
3683         CGparameter fp_Texture_ShadowMapCube;
3684         CGparameter fp_Texture_ShadowMap2D;
3685         CGparameter fp_Texture_CubeProjection;
3686         CGparameter fp_Texture_ScreenDepth;
3687         CGparameter fp_Texture_ScreenNormalMap;
3688         CGparameter fp_Texture_ScreenDiffuse;
3689         CGparameter fp_Texture_ScreenSpecular;
3690         CGparameter fp_Alpha;
3691         CGparameter fp_BloomBlur_Parameters;
3692         CGparameter fp_ClientTime;
3693         CGparameter fp_Color_Ambient;
3694         CGparameter fp_Color_Diffuse;
3695         CGparameter fp_Color_Specular;
3696         CGparameter fp_Color_Glow;
3697         CGparameter fp_Color_Pants;
3698         CGparameter fp_Color_Shirt;
3699         CGparameter fp_DeferredColor_Ambient;
3700         CGparameter fp_DeferredColor_Diffuse;
3701         CGparameter fp_DeferredColor_Specular;
3702         CGparameter fp_DeferredMod_Diffuse;
3703         CGparameter fp_DeferredMod_Specular;
3704         CGparameter fp_DistortScaleRefractReflect;
3705         CGparameter fp_EyePosition;
3706         CGparameter fp_FogColor;
3707         CGparameter fp_FogHeightFade;
3708         CGparameter fp_FogPlane;
3709         CGparameter fp_FogPlaneViewDist;
3710         CGparameter fp_FogRangeRecip;
3711         CGparameter fp_LightColor;
3712         CGparameter fp_LightDir;
3713         CGparameter fp_LightPosition;
3714         CGparameter fp_OffsetMapping_Scale;
3715         CGparameter fp_PixelSize;
3716         CGparameter fp_ReflectColor;
3717         CGparameter fp_ReflectFactor;
3718         CGparameter fp_ReflectOffset;
3719         CGparameter fp_RefractColor;
3720         CGparameter fp_Saturation;
3721         CGparameter fp_ScreenCenterRefractReflect;
3722         CGparameter fp_ScreenScaleRefractReflect;
3723         CGparameter fp_ScreenToDepth;
3724         CGparameter fp_ShadowMap_Parameters;
3725         CGparameter fp_ShadowMap_TextureScale;
3726         CGparameter fp_SpecularPower;
3727         CGparameter fp_UserVec1;
3728         CGparameter fp_UserVec2;
3729         CGparameter fp_UserVec3;
3730         CGparameter fp_UserVec4;
3731         CGparameter fp_ViewTintColor;
3732         CGparameter fp_ViewToLight;
3733 }
3734 r_cg_permutation_t;
3735
3736 /// information about each possible shader permutation
3737 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3738 /// currently selected permutation
3739 r_cg_permutation_t *r_cg_permutation;
3740 /// storage for permutations linked in the hash table
3741 memexpandablearray_t r_cg_permutationarray;
3742
3743 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
3744
3745 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3746 {
3747         //unsigned int hashdepth = 0;
3748         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3749         r_cg_permutation_t *p;
3750         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3751         {
3752                 if (p->mode == mode && p->permutation == permutation)
3753                 {
3754                         //if (hashdepth > 10)
3755                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3756                         return p;
3757                 }
3758                 //hashdepth++;
3759         }
3760         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3761         p->mode = mode;
3762         p->permutation = permutation;
3763         p->hashnext = r_cg_permutationhash[mode][hashindex];
3764         r_cg_permutationhash[mode][hashindex] = p;
3765         //if (hashdepth > 10)
3766         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3767         return p;
3768 }
3769
3770 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3771 {
3772         char *shaderstring;
3773         if (!filename || !filename[0])
3774                 return NULL;
3775         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3776         if (shaderstring)
3777         {
3778                 if (printfromdisknotice)
3779                         Con_DPrintf("from disk %s... ", filename);
3780                 return shaderstring;
3781         }
3782         else if (!strcmp(filename, "cg/default.cg"))
3783         {
3784                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3785                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3786         }
3787         return shaderstring;
3788 }
3789
3790 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3791 {
3792         int i;
3793         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3794         int vertstrings_count = 0, vertstring_length = 0;
3795         int geomstrings_count = 0, geomstring_length = 0;
3796         int fragstrings_count = 0, fragstring_length = 0;
3797         char *t;
3798         char *vertexstring, *geometrystring, *fragmentstring;
3799         char *vertstring, *geomstring, *fragstring;
3800         const char *vertstrings_list[32+3];
3801         const char *geomstrings_list[32+3];
3802         const char *fragstrings_list[32+3];
3803         char permutationname[256];
3804         CGprofile vertexProfile;
3805         CGprofile fragmentProfile;
3806
3807         if (p->compiled)
3808                 return;
3809         p->compiled = true;
3810         p->vprogram = NULL;
3811         p->fprogram = NULL;
3812
3813         permutationname[0] = 0;
3814         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3815         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3816         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3817
3818         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3819
3820         // the first pretext is which type of shader to compile as
3821         // (later these will all be bound together as a program object)
3822         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3823         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3824         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3825
3826         // the second pretext is the mode (for example a light source)
3827         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3828         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3829         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3830         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3831
3832         // now add all the permutation pretexts
3833         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3834         {
3835                 if (permutation & (1<<i))
3836                 {
3837                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3838                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3839                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3840                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3841                 }
3842                 else
3843                 {
3844                         // keep line numbers correct
3845                         vertstrings_list[vertstrings_count++] = "\n";
3846                         geomstrings_list[geomstrings_count++] = "\n";
3847                         fragstrings_list[fragstrings_count++] = "\n";
3848                 }
3849         }
3850
3851         // now append the shader text itself
3852         vertstrings_list[vertstrings_count++] = vertexstring;
3853         geomstrings_list[geomstrings_count++] = geometrystring;
3854         fragstrings_list[fragstrings_count++] = fragmentstring;
3855
3856         // if any sources were NULL, clear the respective list
3857         if (!vertexstring)
3858                 vertstrings_count = 0;
3859         if (!geometrystring)
3860                 geomstrings_count = 0;
3861         if (!fragmentstring)
3862                 fragstrings_count = 0;
3863
3864         vertstring_length = 0;
3865         for (i = 0;i < vertstrings_count;i++)
3866                 vertstring_length += strlen(vertstrings_list[i]);
3867         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3868         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3869                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3870
3871         geomstring_length = 0;
3872         for (i = 0;i < geomstrings_count;i++)
3873                 geomstring_length += strlen(geomstrings_list[i]);
3874         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3875         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3876                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3877
3878         fragstring_length = 0;
3879         for (i = 0;i < fragstrings_count;i++)
3880                 fragstring_length += strlen(fragstrings_list[i]);
3881         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3882         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3883                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3884
3885         CHECKGLERROR
3886         CHECKCGERROR
3887         //vertexProfile = CG_PROFILE_ARBVP1;
3888         //fragmentProfile = CG_PROFILE_ARBFP1;
3889         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3890         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3891         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3892         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3893         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3894         CHECKGLERROR
3895
3896         // compile the vertex program
3897         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL)))
3898         {
3899                 CHECKCGERROR
3900                 cgCompileProgram(p->vprogram);CHECKCGERROR
3901                 if (!cgIsProgramCompiled(p->vprogram))
3902                 {
3903                         CHECKCGERROR
3904                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3905                         p->vprogram = 0;
3906                 }
3907                 else
3908                 {
3909                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3910                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3911                         // look up all the uniform variable names we care about, so we don't
3912                         // have to look them up every time we set them
3913                         CHECKCGERROR
3914                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3915                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3916                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3917                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3918                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3919                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3920                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3921                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3922                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3923                         CHECKCGERROR
3924                 }
3925         }
3926
3927         // compile the fragment program
3928         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL)))
3929         {
3930                 cgCompileProgram(p->fprogram);CHECKCGERROR
3931                 if (!cgIsProgramCompiled(p->fprogram))
3932                 {
3933                         CHECKCGERROR
3934                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3935                         p->fprogram = 0;
3936                 }
3937                 else
3938                 {
3939                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3940                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3941                         CHECKCGERROR
3942                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3943                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3944                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3945                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3946                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3947                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3948                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3949                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3950                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3951                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3952                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3953                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3954                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3955                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3956                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3957                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3958                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3959                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3960                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3961                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3962                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3963                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3964                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3965                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3966                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3967                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3968                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3969                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3970                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
3971                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3972                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
3973                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
3974                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
3975                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
3976                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
3977                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
3978                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
3979                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
3980                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
3981                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
3982                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
3983                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
3984                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
3985                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
3986                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
3987                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
3988                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
3989                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
3990                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
3991                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
3992                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
3993                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
3994                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
3995                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
3996                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
3997                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
3998                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
3999                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4000                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4001                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4002                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4003                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4004                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4005                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4006                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4007                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4008                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4009                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4010                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4011                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4012                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4013                         CHECKCGERROR
4014                 }
4015         }
4016
4017         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4018                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4019         else
4020                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4021
4022         // free the strings
4023         if (vertstring)
4024                 Mem_Free(vertstring);
4025         if (geomstring)
4026                 Mem_Free(geomstring);
4027         if (fragstring)
4028                 Mem_Free(fragstring);
4029         if (vertexstring)
4030                 Mem_Free(vertexstring);
4031         if (geometrystring)
4032                 Mem_Free(geometrystring);
4033         if (fragmentstring)
4034                 Mem_Free(fragmentstring);
4035 }
4036
4037 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4038 {
4039         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4040         CHECKGLERROR
4041         CHECKCGERROR
4042         if (r_cg_permutation != perm)
4043         {
4044                 r_cg_permutation = perm;
4045                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4046                 {
4047                         if (!r_cg_permutation->compiled)
4048                                 R_CG_CompilePermutation(perm, mode, permutation);
4049                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4050                         {
4051                                 // remove features until we find a valid permutation
4052                                 int i;
4053                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4054                                 {
4055                                         // reduce i more quickly whenever it would not remove any bits
4056                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4057                                         if (!(permutation & j))
4058                                                 continue;
4059                                         permutation -= j;
4060                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4061                                         if (!r_cg_permutation->compiled)
4062                                                 R_CG_CompilePermutation(perm, mode, permutation);
4063                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4064                                                 break;
4065                                 }
4066                                 if (i >= SHADERPERMUTATION_COUNT)
4067                                 {
4068                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4069                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4070                                         return; // no bit left to clear, entire mode is broken
4071                                 }
4072                         }
4073                 }
4074                 CHECKGLERROR
4075                 CHECKCGERROR
4076                 if (r_cg_permutation->vprogram)
4077                 {
4078                         //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4079                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4080                         //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4081                 }
4082                 else
4083                 {
4084                         //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4085                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4086                 }
4087                 if (r_cg_permutation->fprogram)
4088                 {
4089                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4090                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4091                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4092                 }
4093                 else
4094                 {
4095                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4096                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4097                 }
4098         }
4099         CHECKCGERROR
4100         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4101         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4102 }
4103
4104 void CG_BindTexture(CGparameter param, int texnum)
4105 {
4106         cgGLSetTextureParameter(param, texnum);
4107         cgGLEnableTextureParameter(param);
4108 }
4109 #endif
4110
4111 void R_GLSL_Restart_f(void)
4112 {
4113         unsigned int i, limit;
4114         switch(vid.renderpath)
4115         {
4116         case RENDERPATH_GL20:
4117                 {
4118                         r_glsl_permutation_t *p;
4119                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4120                         for (i = 0;i < limit;i++)
4121                         {
4122                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4123                                 {
4124                                         GL_Backend_FreeProgram(p->program);
4125                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4126                                 }
4127                         }
4128                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4129                 }
4130                 break;
4131         case RENDERPATH_CGGL:
4132 #ifdef SUPPORTCG
4133                 {
4134                         r_cg_permutation_t *p;
4135                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4136                         for (i = 0;i < limit;i++)
4137                         {
4138                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4139                                 {
4140                                         if (p->vprogram)
4141                                                 cgDestroyProgram(p->vprogram);
4142                                         if (p->fprogram)
4143                                                 cgDestroyProgram(p->fprogram);
4144                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4145                                 }
4146                         }
4147                 }
4148                 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4149                 break;
4150 #endif
4151         case RENDERPATH_GL13:
4152         case RENDERPATH_GL11:
4153                 break;
4154         }
4155 }
4156
4157 void R_GLSL_DumpShader_f(void)
4158 {
4159         int i;
4160         qfile_t *file;
4161
4162         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4163         if (file)
4164         {
4165                 FS_Print(file, "/* The engine may define the following macros:\n");
4166                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4167                 for (i = 0;i < SHADERMODE_COUNT;i++) {
4168                         if (glslshadermodeinfo[i].pretext)
4169                                 FS_Print(file, glslshadermodeinfo[i].pretext);
4170                 }
4171                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++) {
4172                         if (shaderpermutationinfo[i].pretext)
4173                                 FS_Print(file, shaderpermutationinfo[i].pretext);
4174                 }
4175                 FS_Print(file, "*/\n");
4176                 FS_Print(file, builtinshaderstring);
4177                 FS_Close(file);
4178                 Con_Printf("glsl/default.glsl written\n");
4179         }
4180         else
4181                 Con_Printf("failed to write to glsl/default.glsl\n");
4182
4183 #ifdef SUPPORTCG
4184         file = FS_OpenRealFile("cg/default.cg", "w", false);
4185         if (file)
4186         {
4187                 FS_Print(file, "/* The engine may define the following macros:\n");
4188                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4189                 for (i = 0;i < SHADERMODE_COUNT;i++)
4190                         FS_Print(file, cgshadermodeinfo[i].pretext);
4191                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4192                         FS_Print(file, shaderpermutationinfo[i].pretext);
4193                 FS_Print(file, "*/\n");
4194                 FS_Print(file, builtincgshaderstring);
4195                 FS_Close(file);
4196                 Con_Printf("cg/default.cg written\n");
4197         }
4198         else
4199                 Con_Printf("failed to write to cg/default.cg\n");
4200 #endif
4201 }
4202
4203 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4204 {
4205         if (!second)
4206                 texturemode = GL_MODULATE;
4207         switch (vid.renderpath)
4208         {
4209         case RENDERPATH_GL20:
4210                 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))));
4211                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4212                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4213                 break;
4214         case RENDERPATH_CGGL:
4215 #ifdef SUPPORTCG
4216                 CHECKCGERROR
4217                 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))));
4218                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4219                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4220 #endif
4221                 break;
4222         case RENDERPATH_GL13:
4223                 R_Mesh_TexBind(0, first );
4224                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4225                 R_Mesh_TexBind(1, second);
4226                 if (second)
4227                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4228                 break;
4229         case RENDERPATH_GL11:
4230                 R_Mesh_TexBind(0, first );
4231                 break;
4232         }
4233 }
4234
4235 void R_SetupShader_DepthOrShadow(void)
4236 {
4237         switch (vid.renderpath)
4238         {
4239         case RENDERPATH_GL20:
4240                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4241                 break;
4242         case RENDERPATH_CGGL:
4243 #ifdef SUPPORTCG
4244                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4245 #endif
4246                 break;
4247         case RENDERPATH_GL13:
4248                 R_Mesh_TexBind(0, 0);
4249                 R_Mesh_TexBind(1, 0);
4250                 break;
4251         case RENDERPATH_GL11:
4252                 R_Mesh_TexBind(0, 0);
4253                 break;
4254         }
4255 }
4256
4257 void R_SetupShader_ShowDepth(void)
4258 {
4259         switch (vid.renderpath)
4260         {
4261         case RENDERPATH_GL20:
4262                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4263                 break;
4264         case RENDERPATH_CGGL:
4265 #ifdef SUPPORTCG
4266                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4267 #endif
4268                 break;
4269         case RENDERPATH_GL13:
4270                 break;
4271         case RENDERPATH_GL11:
4272                 break;
4273         }
4274 }
4275
4276 extern qboolean r_shadow_usingdeferredprepass;
4277 extern cvar_t r_shadow_deferred_8bitrange;
4278 extern rtexture_t *r_shadow_attenuationgradienttexture;
4279 extern rtexture_t *r_shadow_attenuation2dtexture;
4280 extern rtexture_t *r_shadow_attenuation3dtexture;
4281 extern qboolean r_shadow_usingshadowmaprect;
4282 extern qboolean r_shadow_usingshadowmapcube;
4283 extern qboolean r_shadow_usingshadowmap2d;
4284 extern float r_shadow_shadowmap_texturescale[2];
4285 extern float r_shadow_shadowmap_parameters[4];
4286 extern qboolean r_shadow_shadowmapvsdct;
4287 extern qboolean r_shadow_shadowmapsampler;
4288 extern int r_shadow_shadowmappcf;
4289 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4290 extern rtexture_t *r_shadow_shadowmap2dtexture;
4291 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4292 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4293 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4294 extern int r_shadow_prepass_width;
4295 extern int r_shadow_prepass_height;
4296 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4297 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4298 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4299 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4300 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4301 {
4302         // select a permutation of the lighting shader appropriate to this
4303         // combination of texture, entity, light source, and fogging, only use the
4304         // minimum features necessary to avoid wasting rendering time in the
4305         // fragment shader on features that are not being used
4306         unsigned int permutation = 0;
4307         unsigned int mode = 0;
4308         float m16f[16];
4309         if (rsurfacepass == RSURFPASS_BACKGROUND)
4310         {
4311                 // distorted background
4312                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4313                         mode = SHADERMODE_WATER;
4314                 else
4315                         mode = SHADERMODE_REFRACTION;
4316                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4317                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4318                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4319                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4320                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4321                 R_Mesh_ColorPointer(NULL, 0, 0);
4322                 GL_AlphaTest(false);
4323                 GL_BlendFunc(GL_ONE, GL_ZERO);
4324         }
4325         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4326         {
4327                 if (r_glsl_offsetmapping.integer)
4328                 {
4329                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4330                         if (r_glsl_offsetmapping_reliefmapping.integer)
4331                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4332                 }
4333                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4334                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4335                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4336                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4337                 // normalmap (deferred prepass), may use alpha test on diffuse
4338                 mode = SHADERMODE_DEFERREDGEOMETRY;
4339                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4340                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4341                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4342                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4343                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4344                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4345                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4346                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4347                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4348                 else
4349                         R_Mesh_ColorPointer(NULL, 0, 0);
4350                 GL_AlphaTest(false);
4351                 GL_BlendFunc(GL_ONE, GL_ZERO);
4352         }
4353         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4354         {
4355                 if (r_glsl_offsetmapping.integer)
4356                 {
4357                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4358                         if (r_glsl_offsetmapping_reliefmapping.integer)
4359                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4360                 }
4361                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4362                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4363                 // light source
4364                 mode = SHADERMODE_LIGHTSOURCE;
4365                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4366                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4367                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4368                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4369                 if (diffusescale > 0)
4370                         permutation |= SHADERPERMUTATION_DIFFUSE;
4371                 if (specularscale > 0)
4372                 {
4373                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4374                         if (r_shadow_glossexact.integer)
4375                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4376                 }
4377                 if (r_refdef.fogenabled)
4378                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4379                 if (rsurface.texture->colormapping)
4380                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4381                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4382                 {
4383                         if (r_shadow_usingshadowmaprect)
4384                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4385                         if (r_shadow_usingshadowmap2d)
4386                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4387                         if (r_shadow_usingshadowmapcube)
4388                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4389                         else if(r_shadow_shadowmapvsdct)
4390                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4391
4392                         if (r_shadow_shadowmapsampler)
4393                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4394                         if (r_shadow_shadowmappcf > 1)
4395                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4396                         else if (r_shadow_shadowmappcf)
4397                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4398                 }
4399                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4400                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4401                 {
4402                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4403                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4404                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4405                 }
4406                 else
4407                 {
4408                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4409                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4410                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4411                 }
4412                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4413                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4414                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4415                 else
4416                         R_Mesh_ColorPointer(NULL, 0, 0);
4417                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4418                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4419         }
4420         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4421         {
4422                 if (r_glsl_offsetmapping.integer)
4423                 {
4424                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4425                         if (r_glsl_offsetmapping_reliefmapping.integer)
4426                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4427                 }
4428                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4429                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4430                 // unshaded geometry (fullbright or ambient model lighting)
4431                 mode = SHADERMODE_FLATCOLOR;
4432                 ambientscale = diffusescale = specularscale = 0;
4433                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4434                         permutation |= SHADERPERMUTATION_GLOW;
4435                 if (r_refdef.fogenabled)
4436                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4437                 if (rsurface.texture->colormapping)
4438                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4439                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4440                         permutation |= SHADERPERMUTATION_REFLECTION;
4441                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4442                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4443                 {
4444                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4445                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4446                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4447                 }
4448                 else
4449                 {
4450                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4451                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4452                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4453                 }
4454                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4455                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4456                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4457                 else
4458                         R_Mesh_ColorPointer(NULL, 0, 0);
4459                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4460                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4461         }
4462         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4463         {
4464                 if (r_glsl_offsetmapping.integer)
4465                 {
4466                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4467                         if (r_glsl_offsetmapping_reliefmapping.integer)
4468                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4469                 }
4470                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4471                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4472                 // directional model lighting
4473                 mode = SHADERMODE_LIGHTDIRECTION;
4474                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4475                         permutation |= SHADERPERMUTATION_GLOW;
4476                 permutation |= SHADERPERMUTATION_DIFFUSE;
4477                 if (specularscale > 0)
4478                 {
4479                         permutation |= SHADERPERMUTATION_SPECULAR;
4480                         if (r_shadow_glossexact.integer)
4481                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4482                 }
4483                 if (r_refdef.fogenabled)
4484                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4485                 if (rsurface.texture->colormapping)
4486                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4487                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4488                         permutation |= SHADERPERMUTATION_REFLECTION;
4489                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4490                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4491                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4492                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4493                 {
4494                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4495                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4496                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4497                 }
4498                 else
4499                 {
4500                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4501                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4502                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4503                 }
4504                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4505                 R_Mesh_ColorPointer(NULL, 0, 0);
4506                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4507                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4508         }
4509         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4510         {
4511                 if (r_glsl_offsetmapping.integer)
4512                 {
4513                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4514                         if (r_glsl_offsetmapping_reliefmapping.integer)
4515                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4516                 }
4517                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4518                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4519                 // ambient model lighting
4520                 mode = SHADERMODE_LIGHTDIRECTION;
4521                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4522                         permutation |= SHADERPERMUTATION_GLOW;
4523                 if (r_refdef.fogenabled)
4524                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4525                 if (rsurface.texture->colormapping)
4526                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4527                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4528                         permutation |= SHADERPERMUTATION_REFLECTION;
4529                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4530                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4531                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4532                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4533                 {
4534                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4535                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4536                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4537                 }
4538                 else
4539                 {
4540                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4541                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4542                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4543                 }
4544                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4545                 R_Mesh_ColorPointer(NULL, 0, 0);
4546                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4547                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4548         }
4549         else
4550         {
4551                 if (r_glsl_offsetmapping.integer)
4552                 {
4553                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4554                         if (r_glsl_offsetmapping_reliefmapping.integer)
4555                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4556                 }
4557                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4558                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4559                 // lightmapped wall
4560                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4561                         permutation |= SHADERPERMUTATION_GLOW;
4562                 if (r_refdef.fogenabled)
4563                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4564                 if (rsurface.texture->colormapping)
4565                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4566                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4567                         permutation |= SHADERPERMUTATION_REFLECTION;
4568                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4569                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4570                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4571                 {
4572                         // deluxemapping (light direction texture)
4573                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4574                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4575                         else
4576                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4577                         permutation |= SHADERPERMUTATION_DIFFUSE;
4578                         if (specularscale > 0)
4579                         {
4580                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4581                                 if (r_shadow_glossexact.integer)
4582                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4583                         }
4584                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4585                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4586                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4587                         else
4588                                 R_Mesh_ColorPointer(NULL, 0, 0);
4589                 }
4590                 else if (r_glsl_deluxemapping.integer >= 2)
4591                 {
4592                         // fake deluxemapping (uniform light direction in tangentspace)
4593                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4594                         permutation |= SHADERPERMUTATION_DIFFUSE;
4595                         if (specularscale > 0)
4596                         {
4597                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4598                                 if (r_shadow_glossexact.integer)
4599                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4600                         }
4601                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4602                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4603                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4604                         else
4605                                 R_Mesh_ColorPointer(NULL, 0, 0);
4606                 }
4607                 else if (rsurface.uselightmaptexture)
4608                 {
4609                         // ordinary lightmapping (q1bsp, q3bsp)
4610                         mode = SHADERMODE_LIGHTMAP;
4611                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4612                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4613                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4614                         else
4615                                 R_Mesh_ColorPointer(NULL, 0, 0);
4616                 }
4617                 else
4618                 {
4619                         // ordinary vertex coloring (q3bsp)
4620                         mode = SHADERMODE_VERTEXCOLOR;
4621                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4622                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4623                 }
4624                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4625                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4626                 {
4627                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4628                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4629                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4630                 }
4631                 else
4632                 {
4633                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4634                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4635                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4636                 }
4637                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4638                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4639         }
4640         switch(vid.renderpath)
4641         {
4642         case RENDERPATH_GL20:
4643                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4644                 if (mode == SHADERMODE_LIGHTSOURCE)
4645                 {
4646                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4647                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4648                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4649                         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);
4650                         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);
4651                         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);
4652         
4653                         // additive passes are only darkened by fog, not tinted
4654                         if (r_glsl_permutation->loc_FogColor >= 0)
4655                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4656                         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]);
4657                         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]);
4658                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4659                 }
4660                 else
4661                 {
4662                         if (mode == SHADERMODE_FLATCOLOR)
4663                         {
4664                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4665                         }
4666                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4667                         {
4668                                 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]);
4669                                 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]);
4670                                 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);
4671                                 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);
4672                                 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);
4673                                 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]);
4674                                 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]);
4675                         }
4676                         else
4677                         {
4678                                 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]);
4679                                 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]);
4680                                 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);
4681                                 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);
4682                                 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);
4683                         }
4684                         // additive passes are only darkened by fog, not tinted
4685                         if (r_glsl_permutation->loc_FogColor >= 0)
4686                         {
4687                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4688                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4689                                 else
4690                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4691                         }
4692                         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);
4693                         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]);
4694                         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]);
4695                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4696                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4697                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4698                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4699                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4700                 }
4701                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4702                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4703                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4704                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4705                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4706                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4707                 {
4708                         if (rsurface.texture->pantstexture)
4709                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4710                         else
4711                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4712                 }
4713                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4714                 {
4715                         if (rsurface.texture->shirttexture)
4716                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4717                         else
4718                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4719                 }
4720                 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]);
4721                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4722                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4723                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4724                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4725                 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]);
4726
4727         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4728         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4729         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4730                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4731                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4732                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4733                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4734                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4735                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4736                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4737                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4738                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4739                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4740                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4741                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4742                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4743                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4744                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4745                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4746                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4747                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4748                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4749                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4750                 if (rsurface.rtlight)
4751                 {
4752                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4753                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4754                         if (r_shadow_usingshadowmapcube)
4755                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4756                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4757                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4758                 }
4759                 CHECKGLERROR
4760                 break;
4761         case RENDERPATH_CGGL:
4762 #ifdef SUPPORTCG
4763                 R_SetupShader_SetPermutationCG(mode, permutation);
4764                 if (mode == SHADERMODE_LIGHTSOURCE)
4765                 {
4766                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4767                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4768                 }
4769                 else
4770                 {
4771                         if (mode == SHADERMODE_LIGHTDIRECTION)
4772                         {
4773                                 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
4774                         }
4775                 }
4776                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4777                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4778                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4779                 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
4780                 CHECKGLERROR
4781
4782                 if (mode == SHADERMODE_LIGHTSOURCE)
4783                 {
4784                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4785                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4786                         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
4787                         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
4788                         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
4789
4790                         // additive passes are only darkened by fog, not tinted
4791                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4792                         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
4793                         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
4794                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4795                 }
4796                 else
4797                 {
4798                         if (mode == SHADERMODE_FLATCOLOR)
4799                         {
4800                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4801                         }
4802                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4803                         {
4804                                 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
4805                                 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
4806                                 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
4807                                 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
4808                                 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
4809                                 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
4810                                 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
4811                         }
4812                         else
4813                         {
4814                                 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
4815                                 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
4816                                 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
4817                                 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
4818                                 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
4819                         }
4820                         // additive passes are only darkened by fog, not tinted
4821                         if (r_cg_permutation->fp_FogColor)
4822                         {
4823                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4824                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4825                                 else
4826                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4827                                 CHECKCGERROR
4828                         }
4829                         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
4830                         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
4831                         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
4832                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4833                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4834                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4835                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4836                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4837                 }
4838                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4839                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4840                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4841                 if (r_cg_permutation->fp_Color_Pants)
4842                 {
4843                         if (rsurface.texture->pantstexture)
4844                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4845                         else
4846                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4847                         CHECKCGERROR
4848                 }
4849                 if (r_cg_permutation->fp_Color_Shirt)
4850                 {
4851                         if (rsurface.texture->shirttexture)
4852                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4853                         else
4854                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4855                         CHECKCGERROR
4856                 }
4857                 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
4858                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4859                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4860                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4861                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4862                 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
4863
4864         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
4865         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
4866         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
4867                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
4868                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
4869                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
4870                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
4871                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
4872                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
4873                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
4874                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
4875                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
4876                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
4877                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
4878                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
4879                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
4880                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4881                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
4882                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
4883                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4884                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4885                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
4886                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
4887                 if (rsurface.rtlight)
4888                 {
4889                         if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4890                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4891                         if (r_shadow_usingshadowmapcube)
4892                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4893                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4894                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4895                 }
4896
4897                 CHECKGLERROR
4898 #endif
4899                 break;
4900         case RENDERPATH_GL13:
4901         case RENDERPATH_GL11:
4902                 break;
4903         }
4904 }
4905
4906 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4907 {
4908         // select a permutation of the lighting shader appropriate to this
4909         // combination of texture, entity, light source, and fogging, only use the
4910         // minimum features necessary to avoid wasting rendering time in the
4911         // fragment shader on features that are not being used
4912         unsigned int permutation = 0;
4913         unsigned int mode = 0;
4914         const float *lightcolorbase = rtlight->currentcolor;
4915         float ambientscale = rtlight->ambientscale;
4916         float diffusescale = rtlight->diffusescale;
4917         float specularscale = rtlight->specularscale;
4918         // this is the location of the light in view space
4919         vec3_t viewlightorigin;
4920         // this transforms from view space (camera) to light space (cubemap)
4921         matrix4x4_t viewtolight;
4922         matrix4x4_t lighttoview;
4923         float viewtolight16f[16];
4924         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4925         // light source
4926         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4927         if (rtlight->currentcubemap != r_texture_whitecube)
4928                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4929         if (diffusescale > 0)
4930                 permutation |= SHADERPERMUTATION_DIFFUSE;
4931         if (specularscale > 0)
4932         {
4933                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4934                 if (r_shadow_glossexact.integer)
4935                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4936         }
4937         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4938         {
4939                 if (r_shadow_usingshadowmaprect)
4940                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4941                 if (r_shadow_usingshadowmap2d)
4942                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4943                 if (r_shadow_usingshadowmapcube)
4944                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4945                 else if(r_shadow_shadowmapvsdct)
4946                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4947
4948                 if (r_shadow_shadowmapsampler)
4949                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4950                 if (r_shadow_shadowmappcf > 1)
4951                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4952                 else if (r_shadow_shadowmappcf)
4953                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4954         }
4955         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4956         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4957         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4958         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4959         switch(vid.renderpath)
4960         {
4961         case RENDERPATH_GL20:
4962                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4963                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4964                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4965                 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);
4966                 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);
4967                 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);
4968                 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]);
4969                 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]);
4970                 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));
4971                 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]);
4972
4973                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
4974                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
4975                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
4976                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
4977                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
4978                 if (r_shadow_usingshadowmapcube)
4979                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4980                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
4981                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
4982                 break;
4983         case RENDERPATH_CGGL:
4984 #ifdef SUPPORTCG
4985                 R_SetupShader_SetPermutationCG(mode, permutation);
4986                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4987                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4988                 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
4989                 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
4990                 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
4991                 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
4992                 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
4993                 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
4994                 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
4995
4996                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4997                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4998                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4999                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5000                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5001                 if (r_shadow_usingshadowmapcube)
5002                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5003                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5004                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5005 #endif
5006                 break;
5007         case RENDERPATH_GL13:
5008         case RENDERPATH_GL11:
5009                 break;
5010         }
5011 }
5012
5013 #define SKINFRAME_HASH 1024
5014
5015 typedef struct
5016 {
5017         int loadsequence; // incremented each level change
5018         memexpandablearray_t array;
5019         skinframe_t *hash[SKINFRAME_HASH];
5020 }
5021 r_skinframe_t;
5022 r_skinframe_t r_skinframe;
5023
5024 void R_SkinFrame_PrepareForPurge(void)
5025 {
5026         r_skinframe.loadsequence++;
5027         // wrap it without hitting zero
5028         if (r_skinframe.loadsequence >= 200)
5029                 r_skinframe.loadsequence = 1;
5030 }
5031
5032 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5033 {
5034         if (!skinframe)
5035                 return;
5036         // mark the skinframe as used for the purging code
5037         skinframe->loadsequence = r_skinframe.loadsequence;
5038 }
5039
5040 void R_SkinFrame_Purge(void)
5041 {
5042         int i;
5043         skinframe_t *s;
5044         for (i = 0;i < SKINFRAME_HASH;i++)
5045         {
5046                 for (s = r_skinframe.hash[i];s;s = s->next)
5047                 {
5048                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5049                         {
5050                                 if (s->merged == s->base)
5051                                         s->merged = NULL;
5052                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5053                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5054                                 R_PurgeTexture(s->merged);s->merged = NULL;
5055                                 R_PurgeTexture(s->base  );s->base   = NULL;
5056                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5057                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5058                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5059                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5060                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5061                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5062                                 s->loadsequence = 0;
5063                         }
5064                 }
5065         }
5066 }
5067
5068 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5069         skinframe_t *item;
5070         char basename[MAX_QPATH];
5071
5072         Image_StripImageExtension(name, basename, sizeof(basename));
5073
5074         if( last == NULL ) {
5075                 int hashindex;
5076                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5077                 item = r_skinframe.hash[hashindex];
5078         } else {
5079                 item = last->next;
5080         }
5081
5082         // linearly search through the hash bucket
5083         for( ; item ; item = item->next ) {
5084                 if( !strcmp( item->basename, basename ) ) {
5085                         return item;
5086                 }
5087         }
5088         return NULL;
5089 }
5090
5091 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5092 {
5093         skinframe_t *item;
5094         int hashindex;
5095         char basename[MAX_QPATH];
5096
5097         Image_StripImageExtension(name, basename, sizeof(basename));
5098
5099         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5100         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5101                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5102                         break;
5103
5104         if (!item) {
5105                 rtexture_t *dyntexture;
5106                 // check whether its a dynamic texture
5107                 dyntexture = CL_GetDynTexture( basename );
5108                 if (!add && !dyntexture)
5109                         return NULL;
5110                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5111                 memset(item, 0, sizeof(*item));
5112                 strlcpy(item->basename, basename, sizeof(item->basename));
5113                 item->base = dyntexture; // either NULL or dyntexture handle
5114                 item->textureflags = textureflags;
5115                 item->comparewidth = comparewidth;
5116                 item->compareheight = compareheight;
5117                 item->comparecrc = comparecrc;
5118                 item->next = r_skinframe.hash[hashindex];
5119                 r_skinframe.hash[hashindex] = item;
5120         }
5121         else if( item->base == NULL )
5122         {
5123                 rtexture_t *dyntexture;
5124                 // check whether its a dynamic texture
5125                 // 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]
5126                 dyntexture = CL_GetDynTexture( basename );
5127                 item->base = dyntexture; // either NULL or dyntexture handle
5128         }
5129
5130         R_SkinFrame_MarkUsed(item);
5131         return item;
5132 }
5133
5134 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5135         { \
5136                 unsigned long long avgcolor[5], wsum; \
5137                 int pix, comp, w; \
5138                 avgcolor[0] = 0; \
5139                 avgcolor[1] = 0; \
5140                 avgcolor[2] = 0; \
5141                 avgcolor[3] = 0; \
5142                 avgcolor[4] = 0; \
5143                 wsum = 0; \
5144                 for(pix = 0; pix < cnt; ++pix) \
5145                 { \
5146                         w = 0; \
5147                         for(comp = 0; comp < 3; ++comp) \
5148                                 w += getpixel; \
5149                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5150                         { \
5151                                 ++wsum; \
5152                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5153                                 w = getpixel; \
5154                                 for(comp = 0; comp < 3; ++comp) \
5155                                         avgcolor[comp] += getpixel * w; \
5156                                 avgcolor[3] += w; \
5157                         } \
5158                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5159                         avgcolor[4] += getpixel; \
5160                 } \
5161                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5162                         avgcolor[3] = 1; \
5163                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5164                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5165                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5166                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5167         }
5168
5169 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5170 {
5171         int j;
5172         unsigned char *pixels;
5173         unsigned char *bumppixels;
5174         unsigned char *basepixels = NULL;
5175         int basepixels_width = 0;
5176         int basepixels_height = 0;
5177         skinframe_t *skinframe;
5178         rtexture_t *ddsbase = NULL;
5179         qboolean ddshasalpha = false;
5180         float ddsavgcolor[4];
5181         char basename[MAX_QPATH];
5182
5183         if (cls.state == ca_dedicated)
5184                 return NULL;
5185
5186         // return an existing skinframe if already loaded
5187         // if loading of the first image fails, don't make a new skinframe as it
5188         // would cause all future lookups of this to be missing
5189         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5190         if (skinframe && skinframe->base)
5191                 return skinframe;
5192
5193         Image_StripImageExtension(name, basename, sizeof(basename));
5194
5195         // check for DDS texture file first
5196         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5197         {
5198                 basepixels = loadimagepixelsbgra(name, complain, true);
5199                 if (basepixels == NULL)
5200                         return NULL;
5201         }
5202
5203         if (developer_loading.integer)
5204                 Con_Printf("loading skin \"%s\"\n", name);
5205
5206         // we've got some pixels to store, so really allocate this new texture now
5207         if (!skinframe)
5208                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5209         skinframe->stain = NULL;
5210         skinframe->merged = NULL;
5211         skinframe->base = NULL;
5212         skinframe->pants = NULL;
5213         skinframe->shirt = NULL;
5214         skinframe->nmap = NULL;
5215         skinframe->gloss = NULL;
5216         skinframe->glow = NULL;
5217         skinframe->fog = NULL;
5218         skinframe->hasalpha = false;
5219
5220         if (ddsbase)
5221         {
5222                 skinframe->base = ddsbase;
5223                 skinframe->hasalpha = ddshasalpha;
5224                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5225                 if (r_loadfog && skinframe->hasalpha)
5226                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5227                 //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]);
5228         }
5229         else
5230         {
5231                 basepixels_width = image_width;
5232                 basepixels_height = image_height;
5233                 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);
5234                 if (textureflags & TEXF_ALPHA)
5235                 {
5236                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5237                         {
5238                                 if (basepixels[j] < 255)
5239                                 {
5240                                         skinframe->hasalpha = true;
5241                                         break;
5242                                 }
5243                         }
5244                         if (r_loadfog && skinframe->hasalpha)
5245                         {
5246                                 // has transparent pixels
5247                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5248                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5249                                 {
5250                                         pixels[j+0] = 255;
5251                                         pixels[j+1] = 255;
5252                                         pixels[j+2] = 255;
5253                                         pixels[j+3] = basepixels[j+3];
5254                                 }
5255                                 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);
5256                                 Mem_Free(pixels);
5257                         }
5258                 }
5259                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
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                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5262                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5263                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5264                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5265         }
5266
5267         if (r_loaddds)
5268         {
5269                 if (r_loadnormalmap)
5270                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5271                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5272                 if (r_loadgloss)
5273                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5274                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5275                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5276         }
5277
5278         // _norm is the name used by tenebrae and has been adopted as standard
5279         if (r_loadnormalmap && skinframe->nmap == NULL)
5280         {
5281                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5282                 {
5283                         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);
5284                         Mem_Free(pixels);
5285                         pixels = NULL;
5286                 }
5287                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5288                 {
5289                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5290                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5291                         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);
5292                         Mem_Free(pixels);
5293                         Mem_Free(bumppixels);
5294                 }
5295                 else if (r_shadow_bumpscale_basetexture.value > 0)
5296                 {
5297                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5298                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5299                         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);
5300                         Mem_Free(pixels);
5301                 }
5302                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5303                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5304         }
5305
5306         // _luma is supported only for tenebrae compatibility
5307         // _glow is the preferred name
5308         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5309         {
5310                 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);
5311                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5312                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5313                 Mem_Free(pixels);pixels = NULL;
5314         }
5315
5316         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5317         {
5318                 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);
5319                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5320                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5321                 Mem_Free(pixels);
5322                 pixels = NULL;
5323         }
5324
5325         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5326         {
5327                 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);
5328                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5329                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5330                 Mem_Free(pixels);
5331                 pixels = NULL;
5332         }
5333
5334         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5335         {
5336                 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);
5337                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5338                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5339                 Mem_Free(pixels);
5340                 pixels = NULL;
5341         }
5342
5343         if (basepixels)
5344                 Mem_Free(basepixels);
5345
5346         return skinframe;
5347 }
5348
5349 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5350 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5351 {
5352         int i;
5353         unsigned char *temp1, *temp2;
5354         skinframe_t *skinframe;
5355
5356         if (cls.state == ca_dedicated)
5357                 return NULL;
5358
5359         // if already loaded just return it, otherwise make a new skinframe
5360         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5361         if (skinframe && skinframe->base)
5362                 return skinframe;
5363
5364         skinframe->stain = NULL;
5365         skinframe->merged = NULL;
5366         skinframe->base = NULL;
5367         skinframe->pants = NULL;
5368         skinframe->shirt = NULL;
5369         skinframe->nmap = NULL;
5370         skinframe->gloss = NULL;
5371         skinframe->glow = NULL;
5372         skinframe->fog = NULL;
5373         skinframe->hasalpha = false;
5374
5375         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5376         if (!skindata)
5377                 return NULL;
5378
5379         if (developer_loading.integer)
5380                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5381
5382         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5383         {
5384                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5385                 temp2 = temp1 + width * height * 4;
5386                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5387                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5388                 Mem_Free(temp1);
5389         }
5390         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5391         if (textureflags & TEXF_ALPHA)
5392         {
5393                 for (i = 3;i < width * height * 4;i += 4)
5394                 {
5395                         if (skindata[i] < 255)
5396                         {
5397                                 skinframe->hasalpha = true;
5398                                 break;
5399                         }
5400                 }
5401                 if (r_loadfog && skinframe->hasalpha)
5402                 {
5403                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5404                         memcpy(fogpixels, skindata, width * height * 4);
5405                         for (i = 0;i < width * height * 4;i += 4)
5406                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5407                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5408                         Mem_Free(fogpixels);
5409                 }
5410         }
5411
5412         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5413         //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]);
5414
5415         return skinframe;
5416 }
5417
5418 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5419 {
5420         int i;
5421         int featuresmask;
5422         skinframe_t *skinframe;
5423
5424         if (cls.state == ca_dedicated)
5425                 return NULL;
5426
5427         // if already loaded just return it, otherwise make a new skinframe
5428         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5429         if (skinframe && skinframe->base)
5430                 return skinframe;
5431
5432         skinframe->stain = NULL;
5433         skinframe->merged = NULL;
5434         skinframe->base = NULL;
5435         skinframe->pants = NULL;
5436         skinframe->shirt = NULL;
5437         skinframe->nmap = NULL;
5438         skinframe->gloss = NULL;
5439         skinframe->glow = NULL;
5440         skinframe->fog = NULL;
5441         skinframe->hasalpha = false;
5442
5443         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5444         if (!skindata)
5445                 return NULL;
5446
5447         if (developer_loading.integer)
5448                 Con_Printf("loading quake skin \"%s\"\n", name);
5449
5450         // 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)
5451         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5452         memcpy(skinframe->qpixels, skindata, width*height);
5453         skinframe->qwidth = width;
5454         skinframe->qheight = height;
5455
5456         featuresmask = 0;
5457         for (i = 0;i < width * height;i++)
5458                 featuresmask |= palette_featureflags[skindata[i]];
5459
5460         skinframe->hasalpha = false;
5461         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5462         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5463         skinframe->qgeneratemerged = true;
5464         skinframe->qgeneratebase = skinframe->qhascolormapping;
5465         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5466
5467         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5468         //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]);
5469
5470         return skinframe;
5471 }
5472
5473 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5474 {
5475         int width;
5476         int height;
5477         unsigned char *skindata;
5478
5479         if (!skinframe->qpixels)
5480                 return;
5481
5482         if (!skinframe->qhascolormapping)
5483                 colormapped = false;
5484
5485         if (colormapped)
5486         {
5487                 if (!skinframe->qgeneratebase)
5488                         return;
5489         }
5490         else
5491         {
5492                 if (!skinframe->qgeneratemerged)
5493                         return;
5494         }
5495
5496         width = skinframe->qwidth;
5497         height = skinframe->qheight;
5498         skindata = skinframe->qpixels;
5499
5500         if (skinframe->qgeneratenmap)
5501         {
5502                 unsigned char *temp1, *temp2;
5503                 skinframe->qgeneratenmap = false;
5504                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5505                 temp2 = temp1 + width * height * 4;
5506                 // use either a custom palette or the quake palette
5507                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5508                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5509                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5510                 Mem_Free(temp1);
5511         }
5512
5513         if (skinframe->qgenerateglow)
5514         {
5515                 skinframe->qgenerateglow = false;
5516                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5517         }
5518
5519         if (colormapped)
5520         {
5521                 skinframe->qgeneratebase = false;
5522                 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);
5523                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5524                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5525         }
5526         else
5527         {
5528                 skinframe->qgeneratemerged = false;
5529                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5530         }
5531
5532         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5533         {
5534                 Mem_Free(skinframe->qpixels);
5535                 skinframe->qpixels = NULL;
5536         }
5537 }
5538
5539 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)
5540 {
5541         int i;
5542         skinframe_t *skinframe;
5543
5544         if (cls.state == ca_dedicated)
5545                 return NULL;
5546
5547         // if already loaded just return it, otherwise make a new skinframe
5548         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5549         if (skinframe && skinframe->base)
5550                 return skinframe;
5551
5552         skinframe->stain = NULL;
5553         skinframe->merged = NULL;
5554         skinframe->base = NULL;
5555         skinframe->pants = NULL;
5556         skinframe->shirt = NULL;
5557         skinframe->nmap = NULL;
5558         skinframe->gloss = NULL;
5559         skinframe->glow = NULL;
5560         skinframe->fog = NULL;
5561         skinframe->hasalpha = false;
5562
5563         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5564         if (!skindata)
5565                 return NULL;
5566
5567         if (developer_loading.integer)
5568                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5569
5570         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5571         if (textureflags & TEXF_ALPHA)
5572         {
5573                 for (i = 0;i < width * height;i++)
5574                 {
5575                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5576                         {
5577                                 skinframe->hasalpha = true;
5578                                 break;
5579                         }
5580                 }
5581                 if (r_loadfog && skinframe->hasalpha)
5582                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5583         }
5584
5585         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5586         //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]);
5587
5588         return skinframe;
5589 }
5590
5591 skinframe_t *R_SkinFrame_LoadMissing(void)
5592 {
5593         skinframe_t *skinframe;
5594
5595         if (cls.state == ca_dedicated)
5596                 return NULL;
5597
5598         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5599         skinframe->stain = NULL;
5600         skinframe->merged = NULL;
5601         skinframe->base = NULL;
5602         skinframe->pants = NULL;
5603         skinframe->shirt = NULL;
5604         skinframe->nmap = NULL;
5605         skinframe->gloss = NULL;
5606         skinframe->glow = NULL;
5607         skinframe->fog = NULL;
5608         skinframe->hasalpha = false;
5609
5610         skinframe->avgcolor[0] = rand() / RAND_MAX;
5611         skinframe->avgcolor[1] = rand() / RAND_MAX;
5612         skinframe->avgcolor[2] = rand() / RAND_MAX;
5613         skinframe->avgcolor[3] = 1;
5614
5615         return skinframe;
5616 }
5617
5618 void R_Main_FreeViewCache(void)
5619 {
5620         if (r_refdef.viewcache.entityvisible)
5621                 Mem_Free(r_refdef.viewcache.entityvisible);
5622         if (r_refdef.viewcache.world_pvsbits)
5623                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5624         if (r_refdef.viewcache.world_leafvisible)
5625                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5626         if (r_refdef.viewcache.world_surfacevisible)
5627                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5628         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5629 }
5630
5631 void R_Main_ResizeViewCache(void)
5632 {
5633         int numentities = r_refdef.scene.numentities;
5634         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5635         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5636         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5637         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5638         if (r_refdef.viewcache.maxentities < numentities)
5639         {
5640                 r_refdef.viewcache.maxentities = numentities;
5641                 if (r_refdef.viewcache.entityvisible)
5642                         Mem_Free(r_refdef.viewcache.entityvisible);
5643                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5644         }
5645         if (r_refdef.viewcache.world_numclusters != numclusters)
5646         {
5647                 r_refdef.viewcache.world_numclusters = numclusters;
5648                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5649                 if (r_refdef.viewcache.world_pvsbits)
5650                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5651                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5652         }
5653         if (r_refdef.viewcache.world_numleafs != numleafs)
5654         {
5655                 r_refdef.viewcache.world_numleafs = numleafs;
5656                 if (r_refdef.viewcache.world_leafvisible)
5657                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5658                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5659         }
5660         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5661         {
5662                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5663                 if (r_refdef.viewcache.world_surfacevisible)
5664                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5665                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5666         }
5667 }
5668
5669 extern rtexture_t *loadingscreentexture;
5670 void gl_main_start(void)
5671 {
5672         loadingscreentexture = NULL;
5673         r_texture_blanknormalmap = NULL;
5674         r_texture_white = NULL;
5675         r_texture_grey128 = NULL;
5676         r_texture_black = NULL;
5677         r_texture_whitecube = NULL;
5678         r_texture_normalizationcube = NULL;
5679         r_texture_fogattenuation = NULL;
5680         r_texture_gammaramps = NULL;
5681
5682         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5683         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5684
5685         switch(vid.renderpath)
5686         {
5687         case RENDERPATH_GL20:
5688         case RENDERPATH_CGGL:
5689                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5690                 Cvar_SetValueQuick(&gl_combine, 1);
5691                 Cvar_SetValueQuick(&r_glsl, 1);
5692                 r_loadnormalmap = true;
5693                 r_loadgloss = true;
5694                 r_loadfog = false;
5695                 break;
5696         case RENDERPATH_GL13:
5697                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5698                 Cvar_SetValueQuick(&gl_combine, 1);
5699                 Cvar_SetValueQuick(&r_glsl, 0);
5700                 r_loadnormalmap = false;
5701                 r_loadgloss = false;
5702                 r_loadfog = true;
5703                 break;
5704         case RENDERPATH_GL11:
5705                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5706                 Cvar_SetValueQuick(&gl_combine, 0);
5707                 Cvar_SetValueQuick(&r_glsl, 0);
5708                 r_loadnormalmap = false;
5709                 r_loadgloss = false;
5710                 r_loadfog = true;
5711                 break;
5712         }
5713
5714         R_AnimCache_Free();
5715         R_FrameData_Reset();
5716
5717         r_numqueries = 0;
5718         r_maxqueries = 0;
5719         memset(r_queries, 0, sizeof(r_queries));
5720
5721         r_qwskincache = NULL;
5722         r_qwskincache_size = 0;
5723
5724         // set up r_skinframe loading system for textures
5725         memset(&r_skinframe, 0, sizeof(r_skinframe));
5726         r_skinframe.loadsequence = 1;
5727         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5728
5729         r_main_texturepool = R_AllocTexturePool();
5730         R_BuildBlankTextures();
5731         R_BuildNoTexture();
5732         if (vid.support.arb_texture_cube_map)
5733         {
5734                 R_BuildWhiteCube();
5735                 R_BuildNormalizationCube();
5736         }
5737         r_texture_fogattenuation = NULL;
5738         r_texture_gammaramps = NULL;
5739         //r_texture_fogintensity = NULL;
5740         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5741         memset(&r_waterstate, 0, sizeof(r_waterstate));
5742         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5743         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5744 #ifdef SUPPORTCG
5745         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5746         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5747 #endif
5748         memset(&r_svbsp, 0, sizeof (r_svbsp));
5749
5750         r_refdef.fogmasktable_density = 0;
5751 }
5752
5753 void gl_main_shutdown(void)
5754 {
5755         R_AnimCache_Free();
5756         R_FrameData_Reset();
5757
5758         R_Main_FreeViewCache();
5759
5760         if (r_maxqueries)
5761                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5762
5763         r_numqueries = 0;
5764         r_maxqueries = 0;
5765         memset(r_queries, 0, sizeof(r_queries));
5766
5767         r_qwskincache = NULL;
5768         r_qwskincache_size = 0;
5769
5770         // clear out the r_skinframe state
5771         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5772         memset(&r_skinframe, 0, sizeof(r_skinframe));
5773
5774         if (r_svbsp.nodes)
5775                 Mem_Free(r_svbsp.nodes);
5776         memset(&r_svbsp, 0, sizeof (r_svbsp));
5777         R_FreeTexturePool(&r_main_texturepool);
5778         loadingscreentexture = NULL;
5779         r_texture_blanknormalmap = NULL;
5780         r_texture_white = NULL;
5781         r_texture_grey128 = NULL;
5782         r_texture_black = NULL;
5783         r_texture_whitecube = NULL;
5784         r_texture_normalizationcube = NULL;
5785         r_texture_fogattenuation = NULL;
5786         r_texture_gammaramps = NULL;
5787         //r_texture_fogintensity = NULL;
5788         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5789         memset(&r_waterstate, 0, sizeof(r_waterstate));
5790         R_GLSL_Restart_f();
5791 }
5792
5793 extern void CL_ParseEntityLump(char *entitystring);
5794 void gl_main_newmap(void)
5795 {
5796         // FIXME: move this code to client
5797         int l;
5798         char *entities, entname[MAX_QPATH];
5799         if (r_qwskincache)
5800                 Mem_Free(r_qwskincache);
5801         r_qwskincache = NULL;
5802         r_qwskincache_size = 0;
5803         if (cl.worldmodel)
5804         {
5805                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5806                 l = (int)strlen(entname) - 4;
5807                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5808                 {
5809                         memcpy(entname + l, ".ent", 5);
5810                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5811                         {
5812                                 CL_ParseEntityLump(entities);
5813                                 Mem_Free(entities);
5814                                 return;
5815                         }
5816                 }
5817                 if (cl.worldmodel->brush.entities)
5818                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5819         }
5820         R_Main_FreeViewCache();
5821
5822         R_FrameData_Reset();
5823 }
5824
5825 void GL_Main_Init(void)
5826 {
5827         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5828
5829         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5830         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5831         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5832         if (gamemode == GAME_NEHAHRA)
5833         {
5834                 Cvar_RegisterVariable (&gl_fogenable);
5835                 Cvar_RegisterVariable (&gl_fogdensity);
5836                 Cvar_RegisterVariable (&gl_fogred);
5837                 Cvar_RegisterVariable (&gl_foggreen);
5838                 Cvar_RegisterVariable (&gl_fogblue);
5839                 Cvar_RegisterVariable (&gl_fogstart);
5840                 Cvar_RegisterVariable (&gl_fogend);
5841                 Cvar_RegisterVariable (&gl_skyclip);
5842         }
5843         Cvar_RegisterVariable(&r_motionblur);
5844         Cvar_RegisterVariable(&r_motionblur_maxblur);
5845         Cvar_RegisterVariable(&r_motionblur_bmin);
5846         Cvar_RegisterVariable(&r_motionblur_vmin);
5847         Cvar_RegisterVariable(&r_motionblur_vmax);
5848         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5849         Cvar_RegisterVariable(&r_motionblur_randomize);
5850         Cvar_RegisterVariable(&r_damageblur);
5851         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5852         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5853         Cvar_RegisterVariable(&r_equalize_entities_by);
5854         Cvar_RegisterVariable(&r_equalize_entities_to);
5855         Cvar_RegisterVariable(&r_depthfirst);
5856         Cvar_RegisterVariable(&r_useinfinitefarclip);
5857         Cvar_RegisterVariable(&r_farclip_base);
5858         Cvar_RegisterVariable(&r_farclip_world);
5859         Cvar_RegisterVariable(&r_nearclip);
5860         Cvar_RegisterVariable(&r_showbboxes);
5861         Cvar_RegisterVariable(&r_showsurfaces);
5862         Cvar_RegisterVariable(&r_showtris);
5863         Cvar_RegisterVariable(&r_shownormals);
5864         Cvar_RegisterVariable(&r_showlighting);
5865         Cvar_RegisterVariable(&r_showshadowvolumes);
5866         Cvar_RegisterVariable(&r_showcollisionbrushes);
5867         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5868         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5869         Cvar_RegisterVariable(&r_showdisabledepthtest);
5870         Cvar_RegisterVariable(&r_drawportals);
5871         Cvar_RegisterVariable(&r_drawentities);
5872         Cvar_RegisterVariable(&r_cullentities_trace);
5873         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5874         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5875         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5876         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5877         Cvar_RegisterVariable(&r_drawviewmodel);
5878         Cvar_RegisterVariable(&r_speeds);
5879         Cvar_RegisterVariable(&r_fullbrights);
5880         Cvar_RegisterVariable(&r_wateralpha);
5881         Cvar_RegisterVariable(&r_dynamic);
5882         Cvar_RegisterVariable(&r_fullbright);
5883         Cvar_RegisterVariable(&r_shadows);
5884         Cvar_RegisterVariable(&r_shadows_darken);
5885         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5886         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5887         Cvar_RegisterVariable(&r_shadows_throwdistance);
5888         Cvar_RegisterVariable(&r_shadows_throwdirection);
5889         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5890         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5891         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5892         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5893         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5894         Cvar_RegisterVariable(&r_fog_exp2);
5895         Cvar_RegisterVariable(&r_drawfog);
5896         Cvar_RegisterVariable(&r_transparentdepthmasking);
5897         Cvar_RegisterVariable(&r_texture_dds_load);
5898         Cvar_RegisterVariable(&r_texture_dds_save);
5899         Cvar_RegisterVariable(&r_textureunits);
5900         Cvar_RegisterVariable(&gl_combine);
5901         Cvar_RegisterVariable(&r_glsl);
5902         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5903         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5904         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5905         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5906         Cvar_RegisterVariable(&r_glsl_postprocess);
5907         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5908         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5909         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5910         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5911         Cvar_RegisterVariable(&r_water);
5912         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5913         Cvar_RegisterVariable(&r_water_clippingplanebias);
5914         Cvar_RegisterVariable(&r_water_refractdistort);
5915         Cvar_RegisterVariable(&r_water_reflectdistort);
5916         Cvar_RegisterVariable(&r_lerpsprites);
5917         Cvar_RegisterVariable(&r_lerpmodels);
5918         Cvar_RegisterVariable(&r_lerplightstyles);
5919         Cvar_RegisterVariable(&r_waterscroll);
5920         Cvar_RegisterVariable(&r_bloom);
5921         Cvar_RegisterVariable(&r_bloom_colorscale);
5922         Cvar_RegisterVariable(&r_bloom_brighten);
5923         Cvar_RegisterVariable(&r_bloom_blur);
5924         Cvar_RegisterVariable(&r_bloom_resolution);
5925         Cvar_RegisterVariable(&r_bloom_colorexponent);
5926         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5927         Cvar_RegisterVariable(&r_hdr);
5928         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5929         Cvar_RegisterVariable(&r_hdr_glowintensity);
5930         Cvar_RegisterVariable(&r_hdr_range);
5931         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5932         Cvar_RegisterVariable(&developer_texturelogging);
5933         Cvar_RegisterVariable(&gl_lightmaps);
5934         Cvar_RegisterVariable(&r_test);
5935         Cvar_RegisterVariable(&r_batchmode);
5936         Cvar_RegisterVariable(&r_glsl_saturation);
5937         Cvar_RegisterVariable(&r_framedatasize);
5938         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5939                 Cvar_SetValue("r_fullbrights", 0);
5940         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5941
5942         Cvar_RegisterVariable(&r_track_sprites);
5943         Cvar_RegisterVariable(&r_track_sprites_flags);
5944         Cvar_RegisterVariable(&r_track_sprites_scalew);
5945         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5946 }
5947
5948 extern void R_Textures_Init(void);
5949 extern void GL_Draw_Init(void);
5950 extern void GL_Main_Init(void);
5951 extern void R_Shadow_Init(void);
5952 extern void R_Sky_Init(void);
5953 extern void GL_Surf_Init(void);
5954 extern void R_Particles_Init(void);
5955 extern void R_Explosion_Init(void);
5956 extern void gl_backend_init(void);
5957 extern void Sbar_Init(void);
5958 extern void R_LightningBeams_Init(void);
5959 extern void Mod_RenderInit(void);
5960 extern void Font_Init(void);
5961
5962 void Render_Init(void)
5963 {
5964         gl_backend_init();
5965         R_Textures_Init();
5966         GL_Main_Init();
5967         Font_Init();
5968         GL_Draw_Init();
5969         R_Shadow_Init();
5970         R_Sky_Init();
5971         GL_Surf_Init();
5972         Sbar_Init();
5973         R_Particles_Init();
5974         R_Explosion_Init();
5975         R_LightningBeams_Init();
5976         Mod_RenderInit();
5977 }
5978
5979 /*
5980 ===============
5981 GL_Init
5982 ===============
5983 */
5984 extern char *ENGINE_EXTENSIONS;
5985 void GL_Init (void)
5986 {
5987         gl_renderer = (const char *)qglGetString(GL_RENDERER);
5988         gl_vendor = (const char *)qglGetString(GL_VENDOR);
5989         gl_version = (const char *)qglGetString(GL_VERSION);
5990         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5991
5992         if (!gl_extensions)
5993                 gl_extensions = "";
5994         if (!gl_platformextensions)
5995                 gl_platformextensions = "";
5996
5997         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5998         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5999         Con_Printf("GL_VERSION: %s\n", gl_version);
6000         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6001         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6002
6003         VID_CheckExtensions();
6004
6005         // LordHavoc: report supported extensions
6006         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6007
6008         // clear to black (loading plaque will be seen over this)
6009         CHECKGLERROR
6010         qglClearColor(0,0,0,1);CHECKGLERROR
6011         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6012 }
6013
6014 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6015 {
6016         int i;
6017         mplane_t *p;
6018         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6019         {
6020                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6021                 if (i == 4)
6022                         continue;
6023                 p = r_refdef.view.frustum + i;
6024                 switch(p->signbits)
6025                 {
6026                 default:
6027                 case 0:
6028                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6029                                 return true;
6030                         break;
6031                 case 1:
6032                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6033                                 return true;
6034                         break;
6035                 case 2:
6036                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6037                                 return true;
6038                         break;
6039                 case 3:
6040                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6041                                 return true;
6042                         break;
6043                 case 4:
6044                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6045                                 return true;
6046                         break;
6047                 case 5:
6048                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6049                                 return true;
6050                         break;
6051                 case 6:
6052                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6053                                 return true;
6054                         break;
6055                 case 7:
6056                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6057                                 return true;
6058                         break;
6059                 }
6060         }
6061         return false;
6062 }
6063
6064 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6065 {
6066         int i;
6067         const mplane_t *p;
6068         for (i = 0;i < numplanes;i++)
6069         {
6070                 p = planes + i;
6071                 switch(p->signbits)
6072                 {
6073                 default:
6074                 case 0:
6075                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6076                                 return true;
6077                         break;
6078                 case 1:
6079                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6080                                 return true;
6081                         break;
6082                 case 2:
6083                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6084                                 return true;
6085                         break;
6086                 case 3:
6087                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6088                                 return true;
6089                         break;
6090                 case 4:
6091                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6092                                 return true;
6093                         break;
6094                 case 5:
6095                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6096                                 return true;
6097                         break;
6098                 case 6:
6099                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6100                                 return true;
6101                         break;
6102                 case 7:
6103                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6104                                 return true;
6105                         break;
6106                 }
6107         }
6108         return false;
6109 }
6110
6111 //==================================================================================
6112
6113 // LordHavoc: this stores temporary data used within the same frame
6114
6115 qboolean r_framedata_failed;
6116 static size_t r_framedata_size;
6117 static size_t r_framedata_current;
6118 static void *r_framedata_base;
6119
6120 void R_FrameData_Reset(void)
6121 {
6122         if (r_framedata_base)
6123                 Mem_Free(r_framedata_base);
6124         r_framedata_base = NULL;
6125         r_framedata_size = 0;
6126         r_framedata_current = 0;
6127         r_framedata_failed = false;
6128 }
6129
6130 void R_FrameData_NewFrame(void)
6131 {
6132         size_t wantedsize;
6133         if (r_framedata_failed)
6134                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6135         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6136         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6137         if (r_framedata_size != wantedsize)
6138         {
6139                 r_framedata_size = wantedsize;
6140                 if (r_framedata_base)
6141                         Mem_Free(r_framedata_base);
6142                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6143         }
6144         r_framedata_current = 0;
6145         r_framedata_failed = false;
6146 }
6147
6148 void *R_FrameData_Alloc(size_t size)
6149 {
6150         void *data;
6151
6152         // align to 16 byte boundary
6153         size = (size + 15) & ~15;
6154         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6155         r_framedata_current += size;
6156
6157         // check overflow
6158         if (r_framedata_current > r_framedata_size)
6159                 r_framedata_failed = true;
6160
6161         // return NULL on everything after a failure
6162         if (r_framedata_failed)
6163                 return NULL;
6164
6165         return data;
6166 }
6167
6168 void *R_FrameData_Store(size_t size, void *data)
6169 {
6170         void *d = R_FrameData_Alloc(size);
6171         if (d)
6172                 memcpy(d, data, size);
6173         return d;
6174 }
6175
6176 //==================================================================================
6177
6178 // LordHavoc: animcache originally written by Echon, rewritten since then
6179
6180 /**
6181  * Animation cache prevents re-generating mesh data for an animated model
6182  * multiple times in one frame for lighting, shadowing, reflections, etc.
6183  */
6184
6185 void R_AnimCache_Free(void)
6186 {
6187 }
6188
6189 void R_AnimCache_ClearCache(void)
6190 {
6191         int i;
6192         entity_render_t *ent;
6193
6194         for (i = 0;i < r_refdef.scene.numentities;i++)
6195         {
6196                 ent = r_refdef.scene.entities[i];
6197                 ent->animcache_vertex3f = NULL;
6198                 ent->animcache_normal3f = NULL;
6199                 ent->animcache_svector3f = NULL;
6200                 ent->animcache_tvector3f = NULL;
6201         }
6202 }
6203
6204 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6205 {
6206         dp_model_t *model = ent->model;
6207         int numvertices;
6208         // see if it's already cached this frame
6209         if (ent->animcache_vertex3f)
6210         {
6211                 // add normals/tangents if needed
6212                 if (wantnormals || wanttangents)
6213                 {
6214                         if (ent->animcache_normal3f)
6215                                 wantnormals = false;
6216                         if (ent->animcache_svector3f)
6217                                 wanttangents = false;
6218                         if (wantnormals || wanttangents)
6219                         {
6220                                 numvertices = model->surfmesh.num_vertices;
6221                                 if (wantnormals)
6222                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6223                                 if (wanttangents)
6224                                 {
6225                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6226                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6227                                 }
6228                                 if (!r_framedata_failed)
6229                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6230                         }
6231                 }
6232         }
6233         else
6234         {
6235                 // see if this ent is worth caching
6236                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6237                         return false;
6238                 // get some memory for this entity and generate mesh data
6239                 numvertices = model->surfmesh.num_vertices;
6240                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6241                 if (wantnormals)
6242                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6243                 if (wanttangents)
6244                 {
6245                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6246                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6247                 }
6248                 if (!r_framedata_failed)
6249                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6250         }
6251         return !r_framedata_failed;
6252 }
6253
6254 void R_AnimCache_CacheVisibleEntities(void)
6255 {
6256         int i;
6257         qboolean wantnormals = !r_showsurfaces.integer;
6258         qboolean wanttangents = !r_showsurfaces.integer;
6259
6260         switch(vid.renderpath)
6261         {
6262         case RENDERPATH_GL20:
6263         case RENDERPATH_CGGL:
6264                 break;
6265         case RENDERPATH_GL13:
6266         case RENDERPATH_GL11:
6267                 wanttangents = false;
6268                 break;
6269         }
6270
6271         // TODO: thread this
6272         // NOTE: R_PrepareRTLights() also caches entities
6273
6274         for (i = 0;i < r_refdef.scene.numentities;i++)
6275                 if (r_refdef.viewcache.entityvisible[i])
6276                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6277
6278         if (r_shadows.integer)
6279                 for (i = 0;i < r_refdef.scene.numentities;i++)
6280                         if (!r_refdef.viewcache.entityvisible[i])
6281                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6282 }
6283
6284 //==================================================================================
6285
6286 static void R_View_UpdateEntityLighting (void)
6287 {
6288         int i;
6289         entity_render_t *ent;
6290         vec3_t tempdiffusenormal, avg;
6291         vec_t f, fa, fd, fdd;
6292
6293         for (i = 0;i < r_refdef.scene.numentities;i++)
6294         {
6295                 ent = r_refdef.scene.entities[i];
6296
6297                 // skip unseen models
6298                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6299                         continue;
6300
6301                 // skip bsp models
6302                 if (ent->model && ent->model->brush.num_leafs)
6303                 {
6304                         // TODO: use modellight for r_ambient settings on world?
6305                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6306                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6307                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6308                         continue;
6309                 }
6310
6311                 // fetch the lighting from the worldmodel data
6312                 VectorClear(ent->modellight_ambient);
6313                 VectorClear(ent->modellight_diffuse);
6314                 VectorClear(tempdiffusenormal);
6315                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6316                 {
6317                         vec3_t org;
6318                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6319                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6320                         if(ent->flags & RENDER_EQUALIZE)
6321                         {
6322                                 // first fix up ambient lighting...
6323                                 if(r_equalize_entities_minambient.value > 0)
6324                                 {
6325                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6326                                         if(fd > 0)
6327                                         {
6328                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6329                                                 if(fa < r_equalize_entities_minambient.value * fd)
6330                                                 {
6331                                                         // solve:
6332                                                         //   fa'/fd' = minambient
6333                                                         //   fa'+0.25*fd' = fa+0.25*fd
6334                                                         //   ...
6335                                                         //   fa' = fd' * minambient
6336                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6337                                                         //   ...
6338                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6339                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6340                                                         //   ...
6341                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6342                                                         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
6343                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6344                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6345                                                 }
6346                                         }
6347                                 }
6348
6349                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6350                                 {
6351                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6352                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6353                                         if(f > 0)
6354                                         {
6355                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6356                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6357                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6358                                         }
6359                                 }
6360                         }
6361                 }
6362                 else // highly rare
6363                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6364
6365                 // move the light direction into modelspace coordinates for lighting code
6366                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6367                 if(VectorLength2(ent->modellight_lightdir) == 0)
6368                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6369                 VectorNormalize(ent->modellight_lightdir);
6370         }
6371 }
6372
6373 #define MAX_LINEOFSIGHTTRACES 64
6374
6375 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6376 {
6377         int i;
6378         vec3_t boxmins, boxmaxs;
6379         vec3_t start;
6380         vec3_t end;
6381         dp_model_t *model = r_refdef.scene.worldmodel;
6382
6383         if (!model || !model->brush.TraceLineOfSight)
6384                 return true;
6385
6386         // expand the box a little
6387         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6388         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6389         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6390         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6391         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6392         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6393
6394         // try center
6395         VectorCopy(eye, start);
6396         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6397         if (model->brush.TraceLineOfSight(model, start, end))
6398                 return true;
6399
6400         // try various random positions
6401         for (i = 0;i < numsamples;i++)
6402         {
6403                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6404                 if (model->brush.TraceLineOfSight(model, start, end))
6405                         return true;
6406         }
6407
6408         return false;
6409 }
6410
6411
6412 static void R_View_UpdateEntityVisible (void)
6413 {
6414         int i;
6415         int renderimask;
6416         int samples;
6417         entity_render_t *ent;
6418
6419         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6420         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6421         {
6422                 // worldmodel can check visibility
6423                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6424                 for (i = 0;i < r_refdef.scene.numentities;i++)
6425                 {
6426                         ent = r_refdef.scene.entities[i];
6427                         if (!(ent->flags & renderimask))
6428                         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)))
6429                         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))
6430                                 r_refdef.viewcache.entityvisible[i] = true;
6431                 }
6432                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6433                 {
6434                         for (i = 0;i < r_refdef.scene.numentities;i++)
6435                         {
6436                                 ent = r_refdef.scene.entities[i];
6437                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6438                                 {
6439                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6440                                         if (samples < 0)
6441                                                 continue; // temp entities do pvs only
6442                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6443                                                 ent->last_trace_visibility = realtime;
6444                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6445                                                 r_refdef.viewcache.entityvisible[i] = 0;
6446                                 }
6447                         }
6448                 }
6449         }
6450         else
6451         {
6452                 // no worldmodel or it can't check visibility
6453                 for (i = 0;i < r_refdef.scene.numentities;i++)
6454                 {
6455                         ent = r_refdef.scene.entities[i];
6456                         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));
6457                 }
6458         }
6459 }
6460
6461 /// only used if skyrendermasked, and normally returns false
6462 int R_DrawBrushModelsSky (void)
6463 {
6464         int i, sky;
6465         entity_render_t *ent;
6466
6467         sky = false;
6468         for (i = 0;i < r_refdef.scene.numentities;i++)
6469         {
6470                 if (!r_refdef.viewcache.entityvisible[i])
6471                         continue;
6472                 ent = r_refdef.scene.entities[i];
6473                 if (!ent->model || !ent->model->DrawSky)
6474                         continue;
6475                 ent->model->DrawSky(ent);
6476                 sky = true;
6477         }
6478         return sky;
6479 }
6480
6481 static void R_DrawNoModel(entity_render_t *ent);
6482 static void R_DrawModels(void)
6483 {
6484         int i;
6485         entity_render_t *ent;
6486
6487         for (i = 0;i < r_refdef.scene.numentities;i++)
6488         {
6489                 if (!r_refdef.viewcache.entityvisible[i])
6490                         continue;
6491                 ent = r_refdef.scene.entities[i];
6492                 r_refdef.stats.entities++;
6493                 if (ent->model && ent->model->Draw != NULL)
6494                         ent->model->Draw(ent);
6495                 else
6496                         R_DrawNoModel(ent);
6497         }
6498 }
6499
6500 static void R_DrawModelsDepth(void)
6501 {
6502         int i;
6503         entity_render_t *ent;
6504
6505         for (i = 0;i < r_refdef.scene.numentities;i++)
6506         {
6507                 if (!r_refdef.viewcache.entityvisible[i])
6508                         continue;
6509                 ent = r_refdef.scene.entities[i];
6510                 if (ent->model && ent->model->DrawDepth != NULL)
6511                         ent->model->DrawDepth(ent);
6512         }
6513 }
6514
6515 static void R_DrawModelsDebug(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                 if (ent->model && ent->model->DrawDebug != NULL)
6526                         ent->model->DrawDebug(ent);
6527         }
6528 }
6529
6530 static void R_DrawModelsAddWaterPlanes(void)
6531 {
6532         int i;
6533         entity_render_t *ent;
6534
6535         for (i = 0;i < r_refdef.scene.numentities;i++)
6536         {
6537                 if (!r_refdef.viewcache.entityvisible[i])
6538                         continue;
6539                 ent = r_refdef.scene.entities[i];
6540                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6541                         ent->model->DrawAddWaterPlanes(ent);
6542         }
6543 }
6544
6545 static void R_View_SetFrustum(void)
6546 {
6547         int i;
6548         double slopex, slopey;
6549         vec3_t forward, left, up, origin;
6550
6551         // we can't trust r_refdef.view.forward and friends in reflected scenes
6552         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6553
6554 #if 0
6555         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6556         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6557         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6558         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6559         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6560         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6561         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6562         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6563         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6564         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6565         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6566         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6567 #endif
6568
6569 #if 0
6570         zNear = r_refdef.nearclip;
6571         nudge = 1.0 - 1.0 / (1<<23);
6572         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6573         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6574         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6575         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6576         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6577         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6578         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6579         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6580 #endif
6581
6582
6583
6584 #if 0
6585         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6586         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6587         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6588         r_refdef.view.frustum[0].dist = m[15] - m[12];
6589
6590         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6591         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6592         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6593         r_refdef.view.frustum[1].dist = m[15] + m[12];
6594
6595         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6596         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6597         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6598         r_refdef.view.frustum[2].dist = m[15] - m[13];
6599
6600         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6601         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6602         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6603         r_refdef.view.frustum[3].dist = m[15] + m[13];
6604
6605         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6606         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6607         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6608         r_refdef.view.frustum[4].dist = m[15] - m[14];
6609
6610         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6611         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6612         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6613         r_refdef.view.frustum[5].dist = m[15] + m[14];
6614 #endif
6615
6616         if (r_refdef.view.useperspective)
6617         {
6618                 slopex = 1.0 / r_refdef.view.frustum_x;
6619                 slopey = 1.0 / r_refdef.view.frustum_y;
6620                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6621                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6622                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6623                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6624                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6625
6626                 // Leaving those out was a mistake, those were in the old code, and they
6627                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6628                 // I couldn't reproduce it after adding those normalizations. --blub
6629                 VectorNormalize(r_refdef.view.frustum[0].normal);
6630                 VectorNormalize(r_refdef.view.frustum[1].normal);
6631                 VectorNormalize(r_refdef.view.frustum[2].normal);
6632                 VectorNormalize(r_refdef.view.frustum[3].normal);
6633
6634                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6635                 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]);
6636                 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]);
6637                 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]);
6638                 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]);
6639
6640                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6641                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6642                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6643                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6644                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6645         }
6646         else
6647         {
6648                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6649                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6650                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6651                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6652                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6653                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6654                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6655                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6656                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6657                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6658         }
6659         r_refdef.view.numfrustumplanes = 5;
6660
6661         if (r_refdef.view.useclipplane)
6662         {
6663                 r_refdef.view.numfrustumplanes = 6;
6664                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6665         }
6666
6667         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6668                 PlaneClassify(r_refdef.view.frustum + i);
6669
6670         // LordHavoc: note to all quake engine coders, Quake had a special case
6671         // for 90 degrees which assumed a square view (wrong), so I removed it,
6672         // Quake2 has it disabled as well.
6673
6674         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6675         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6676         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6677         //PlaneClassify(&frustum[0]);
6678
6679         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6680         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6681         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6682         //PlaneClassify(&frustum[1]);
6683
6684         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6685         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6686         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6687         //PlaneClassify(&frustum[2]);
6688
6689         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6690         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6691         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6692         //PlaneClassify(&frustum[3]);
6693
6694         // nearclip plane
6695         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6696         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6697         //PlaneClassify(&frustum[4]);
6698 }
6699
6700 void R_View_Update(void)
6701 {
6702         R_Main_ResizeViewCache();
6703         R_View_SetFrustum();
6704         R_View_WorldVisibility(r_refdef.view.useclipplane);
6705         R_View_UpdateEntityVisible();
6706         R_View_UpdateEntityLighting();
6707 }
6708
6709 void R_SetupView(qboolean allowwaterclippingplane)
6710 {
6711         const float *customclipplane = NULL;
6712         float plane[4];
6713         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6714         {
6715                 // LordHavoc: couldn't figure out how to make this approach the
6716                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6717                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6718                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6719                         dist = r_refdef.view.clipplane.dist;
6720                 plane[0] = r_refdef.view.clipplane.normal[0];
6721                 plane[1] = r_refdef.view.clipplane.normal[1];
6722                 plane[2] = r_refdef.view.clipplane.normal[2];
6723                 plane[3] = dist;
6724                 customclipplane = plane;
6725         }
6726
6727         if (!r_refdef.view.useperspective)
6728                 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);
6729         else if (vid.stencil && r_useinfinitefarclip.integer)
6730                 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);
6731         else
6732                 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);
6733         R_SetViewport(&r_refdef.view.viewport);
6734 }
6735
6736 void R_EntityMatrix(const matrix4x4_t *matrix)
6737 {
6738         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6739         {
6740                 gl_modelmatrixchanged = false;
6741                 gl_modelmatrix = *matrix;
6742                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6743                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6744                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6745                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6746                 CHECKGLERROR
6747                 switch(vid.renderpath)
6748                 {
6749                 case RENDERPATH_GL20:
6750                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6751                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6752                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6753                         break;
6754                 case RENDERPATH_CGGL:
6755 #ifdef SUPPORTCG
6756                         CHECKCGERROR
6757                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6758                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6759                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6760 #endif
6761                         break;
6762                 case RENDERPATH_GL13:
6763                 case RENDERPATH_GL11:
6764                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6765                         break;
6766                 }
6767         }
6768 }
6769
6770 void R_ResetViewRendering2D(void)
6771 {
6772         r_viewport_t viewport;
6773         DrawQ_Finish();
6774
6775         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6776         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);
6777         R_SetViewport(&viewport);
6778         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6779         GL_Color(1, 1, 1, 1);
6780         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6781         GL_BlendFunc(GL_ONE, GL_ZERO);
6782         GL_AlphaTest(false);
6783         GL_ScissorTest(false);
6784         GL_DepthMask(false);
6785         GL_DepthRange(0, 1);
6786         GL_DepthTest(false);
6787         R_EntityMatrix(&identitymatrix);
6788         R_Mesh_ResetTextureState();
6789         GL_PolygonOffset(0, 0);
6790         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6791         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6792         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6793         qglStencilMask(~0);CHECKGLERROR
6794         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6795         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6796         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6797 }
6798
6799 void R_ResetViewRendering3D(void)
6800 {
6801         DrawQ_Finish();
6802
6803         R_SetupView(true);
6804         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6805         GL_Color(1, 1, 1, 1);
6806         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6807         GL_BlendFunc(GL_ONE, GL_ZERO);
6808         GL_AlphaTest(false);
6809         GL_ScissorTest(true);
6810         GL_DepthMask(true);
6811         GL_DepthRange(0, 1);
6812         GL_DepthTest(true);
6813         R_EntityMatrix(&identitymatrix);
6814         R_Mesh_ResetTextureState();
6815         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6816         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6817         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6818         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6819         qglStencilMask(~0);CHECKGLERROR
6820         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6821         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6822         GL_CullFace(r_refdef.view.cullface_back);
6823 }
6824
6825 void R_RenderScene(void);
6826 void R_RenderWaterPlanes(void);
6827
6828 static void R_Water_StartFrame(void)
6829 {
6830         int i;
6831         int waterwidth, waterheight, texturewidth, textureheight;
6832         r_waterstate_waterplane_t *p;
6833
6834         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6835                 return;
6836
6837         switch(vid.renderpath)
6838         {
6839         case RENDERPATH_GL20:
6840         case RENDERPATH_CGGL:
6841                 break;
6842         case RENDERPATH_GL13:
6843         case RENDERPATH_GL11:
6844                 return;
6845         }
6846
6847         // set waterwidth and waterheight to the water resolution that will be
6848         // used (often less than the screen resolution for faster rendering)
6849         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6850         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6851
6852         // calculate desired texture sizes
6853         // can't use water if the card does not support the texture size
6854         if (!r_water.integer || r_showsurfaces.integer)
6855                 texturewidth = textureheight = waterwidth = waterheight = 0;
6856         else if (vid.support.arb_texture_non_power_of_two)
6857         {
6858                 texturewidth = waterwidth;
6859                 textureheight = waterheight;
6860         }
6861         else
6862         {
6863                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6864                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6865         }
6866
6867         // allocate textures as needed
6868         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6869         {
6870                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6871                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6872                 {
6873                         if (p->texture_refraction)
6874                                 R_FreeTexture(p->texture_refraction);
6875                         p->texture_refraction = NULL;
6876                         if (p->texture_reflection)
6877                                 R_FreeTexture(p->texture_reflection);
6878                         p->texture_reflection = NULL;
6879                 }
6880                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6881                 r_waterstate.texturewidth = texturewidth;
6882                 r_waterstate.textureheight = textureheight;
6883         }
6884
6885         if (r_waterstate.texturewidth)
6886         {
6887                 r_waterstate.enabled = true;
6888
6889                 // when doing a reduced render (HDR) we want to use a smaller area
6890                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6891                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6892
6893                 // set up variables that will be used in shader setup
6894                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6895                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6896                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6897                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6898         }
6899
6900         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6901         r_waterstate.numwaterplanes = 0;
6902 }
6903
6904 void R_Water_AddWaterPlane(msurface_t *surface)
6905 {
6906         int triangleindex, planeindex;
6907         const int *e;
6908         vec3_t vert[3];
6909         vec3_t normal;
6910         vec3_t center;
6911         mplane_t plane;
6912         r_waterstate_waterplane_t *p;
6913         texture_t *t = R_GetCurrentTexture(surface->texture);
6914         // just use the first triangle with a valid normal for any decisions
6915         VectorClear(normal);
6916         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6917         {
6918                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6919                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6920                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6921                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6922                 if (VectorLength2(normal) >= 0.001)
6923                         break;
6924         }
6925
6926         VectorCopy(normal, plane.normal);
6927         VectorNormalize(plane.normal);
6928         plane.dist = DotProduct(vert[0], plane.normal);
6929         PlaneClassify(&plane);
6930         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6931         {
6932                 // skip backfaces (except if nocullface is set)
6933                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6934                         return;
6935                 VectorNegate(plane.normal, plane.normal);
6936                 plane.dist *= -1;
6937                 PlaneClassify(&plane);
6938         }
6939
6940
6941         // find a matching plane if there is one
6942         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6943                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6944                         break;
6945         if (planeindex >= r_waterstate.maxwaterplanes)
6946                 return; // nothing we can do, out of planes
6947
6948         // if this triangle does not fit any known plane rendered this frame, add one
6949         if (planeindex >= r_waterstate.numwaterplanes)
6950         {
6951                 // store the new plane
6952                 r_waterstate.numwaterplanes++;
6953                 p->plane = plane;
6954                 // clear materialflags and pvs
6955                 p->materialflags = 0;
6956                 p->pvsvalid = false;
6957         }
6958         // merge this surface's materialflags into the waterplane
6959         p->materialflags |= t->currentmaterialflags;
6960         // merge this surface's PVS into the waterplane
6961         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6962         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6963          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6964         {
6965                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6966                 p->pvsvalid = true;
6967         }
6968 }
6969
6970 static void R_Water_ProcessPlanes(void)
6971 {
6972         r_refdef_view_t originalview;
6973         r_refdef_view_t myview;
6974         int planeindex;
6975         r_waterstate_waterplane_t *p;
6976
6977         originalview = r_refdef.view;
6978
6979         // make sure enough textures are allocated
6980         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6981         {
6982                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6983                 {
6984                         if (!p->texture_refraction)
6985                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6986                         if (!p->texture_refraction)
6987                                 goto error;
6988                 }
6989
6990                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6991                 {
6992                         if (!p->texture_reflection)
6993                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6994                         if (!p->texture_reflection)
6995                                 goto error;
6996                 }
6997         }
6998
6999         // render views
7000         r_refdef.view = originalview;
7001         r_refdef.view.showdebug = false;
7002         r_refdef.view.width = r_waterstate.waterwidth;
7003         r_refdef.view.height = r_waterstate.waterheight;
7004         r_refdef.view.useclipplane = true;
7005         myview = r_refdef.view;
7006         r_waterstate.renderingscene = true;
7007         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7008         {
7009                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7010                 {
7011                         r_refdef.view = myview;
7012                         // render reflected scene and copy into texture
7013                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7014                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7015                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7016                         r_refdef.view.clipplane = p->plane;
7017                         // reverse the cullface settings for this render
7018                         r_refdef.view.cullface_front = GL_FRONT;
7019                         r_refdef.view.cullface_back = GL_BACK;
7020                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7021                         {
7022                                 r_refdef.view.usecustompvs = true;
7023                                 if (p->pvsvalid)
7024                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7025                                 else
7026                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7027                         }
7028
7029                         R_ResetViewRendering3D();
7030                         R_ClearScreen(r_refdef.fogenabled);
7031                         R_View_Update();
7032                         R_RenderScene();
7033
7034                         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);
7035                 }
7036
7037                 // render the normal view scene and copy into texture
7038                 // (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)
7039                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7040                 {
7041                         r_refdef.view = myview;
7042                         r_refdef.view.clipplane = p->plane;
7043                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7044                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7045                         PlaneClassify(&r_refdef.view.clipplane);
7046
7047                         R_ResetViewRendering3D();
7048                         R_ClearScreen(r_refdef.fogenabled);
7049                         R_View_Update();
7050                         R_RenderScene();
7051
7052                         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);
7053                 }
7054
7055         }
7056         r_waterstate.renderingscene = false;
7057         r_refdef.view = originalview;
7058         R_ResetViewRendering3D();
7059         R_ClearScreen(r_refdef.fogenabled);
7060         R_View_Update();
7061         return;
7062 error:
7063         r_refdef.view = originalview;
7064         r_waterstate.renderingscene = false;
7065         Cvar_SetValueQuick(&r_water, 0);
7066         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7067         return;
7068 }
7069
7070 void R_Bloom_StartFrame(void)
7071 {
7072         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7073
7074         switch(vid.renderpath)
7075         {
7076         case RENDERPATH_GL20:
7077         case RENDERPATH_CGGL:
7078                 break;
7079         case RENDERPATH_GL13:
7080         case RENDERPATH_GL11:
7081                 return;
7082         }
7083
7084         // set bloomwidth and bloomheight to the bloom resolution that will be
7085         // used (often less than the screen resolution for faster rendering)
7086         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7087         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7088         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7089         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7090         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7091
7092         // calculate desired texture sizes
7093         if (vid.support.arb_texture_non_power_of_two)
7094         {
7095                 screentexturewidth = r_refdef.view.width;
7096                 screentextureheight = r_refdef.view.height;
7097                 bloomtexturewidth = r_bloomstate.bloomwidth;
7098                 bloomtextureheight = r_bloomstate.bloomheight;
7099         }
7100         else
7101         {
7102                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7103                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7104                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7105                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7106         }
7107
7108         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))
7109         {
7110                 Cvar_SetValueQuick(&r_hdr, 0);
7111                 Cvar_SetValueQuick(&r_bloom, 0);
7112                 Cvar_SetValueQuick(&r_motionblur, 0);
7113                 Cvar_SetValueQuick(&r_damageblur, 0);
7114         }
7115
7116         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)))
7117                 screentexturewidth = screentextureheight = 0;
7118         if (!r_hdr.integer && !r_bloom.integer)
7119                 bloomtexturewidth = bloomtextureheight = 0;
7120
7121         // allocate textures as needed
7122         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7123         {
7124                 if (r_bloomstate.texture_screen)
7125                         R_FreeTexture(r_bloomstate.texture_screen);
7126                 r_bloomstate.texture_screen = NULL;
7127                 r_bloomstate.screentexturewidth = screentexturewidth;
7128                 r_bloomstate.screentextureheight = screentextureheight;
7129                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7130                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7131         }
7132         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7133         {
7134                 if (r_bloomstate.texture_bloom)
7135                         R_FreeTexture(r_bloomstate.texture_bloom);
7136                 r_bloomstate.texture_bloom = NULL;
7137                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7138                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7139                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7140                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7141         }
7142
7143         // when doing a reduced render (HDR) we want to use a smaller area
7144         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7145         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7146         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7147         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7148         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7149
7150         // set up a texcoord array for the full resolution screen image
7151         // (we have to keep this around to copy back during final render)
7152         r_bloomstate.screentexcoord2f[0] = 0;
7153         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7154         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7155         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7156         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7157         r_bloomstate.screentexcoord2f[5] = 0;
7158         r_bloomstate.screentexcoord2f[6] = 0;
7159         r_bloomstate.screentexcoord2f[7] = 0;
7160
7161         // set up a texcoord array for the reduced resolution bloom image
7162         // (which will be additive blended over the screen image)
7163         r_bloomstate.bloomtexcoord2f[0] = 0;
7164         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7165         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7166         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7167         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7168         r_bloomstate.bloomtexcoord2f[5] = 0;
7169         r_bloomstate.bloomtexcoord2f[6] = 0;
7170         r_bloomstate.bloomtexcoord2f[7] = 0;
7171
7172         if (r_hdr.integer || r_bloom.integer)
7173         {
7174                 r_bloomstate.enabled = true;
7175                 r_bloomstate.hdr = r_hdr.integer != 0;
7176         }
7177
7178         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);
7179 }
7180
7181 void R_Bloom_CopyBloomTexture(float colorscale)
7182 {
7183         r_refdef.stats.bloom++;
7184
7185         // scale down screen texture to the bloom texture size
7186         CHECKGLERROR
7187         R_SetViewport(&r_bloomstate.viewport);
7188         GL_BlendFunc(GL_ONE, GL_ZERO);
7189         GL_Color(colorscale, colorscale, colorscale, 1);
7190         // TODO: optimize with multitexture or GLSL
7191         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7192         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7193         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7194         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7195
7196         // we now have a bloom image in the framebuffer
7197         // copy it into the bloom image texture for later processing
7198         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);
7199         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7200 }
7201
7202 void R_Bloom_CopyHDRTexture(void)
7203 {
7204         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);
7205         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7206 }
7207
7208 void R_Bloom_MakeTexture(void)
7209 {
7210         int x, range, dir;
7211         float xoffset, yoffset, r, brighten;
7212
7213         r_refdef.stats.bloom++;
7214
7215         R_ResetViewRendering2D();
7216         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7217         R_Mesh_ColorPointer(NULL, 0, 0);
7218
7219         // we have a bloom image in the framebuffer
7220         CHECKGLERROR
7221         R_SetViewport(&r_bloomstate.viewport);
7222
7223         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7224         {
7225                 x *= 2;
7226                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7227                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7228                 GL_Color(r, r, r, 1);
7229                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7230                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7231                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7232                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7233
7234                 // copy the vertically blurred bloom view to a texture
7235                 GL_ActiveTexture(0);
7236                 CHECKGLERROR
7237                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7238                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7239         }
7240
7241         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7242         brighten = r_bloom_brighten.value;
7243         if (r_hdr.integer)
7244                 brighten *= r_hdr_range.value;
7245         brighten = sqrt(brighten);
7246         if(range >= 1)
7247                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7248         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7249         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7250
7251         for (dir = 0;dir < 2;dir++)
7252         {
7253                 // blend on at multiple vertical offsets to achieve a vertical blur
7254                 // TODO: do offset blends using GLSL
7255                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7256                 GL_BlendFunc(GL_ONE, GL_ZERO);
7257                 for (x = -range;x <= range;x++)
7258                 {
7259                         if (!dir){xoffset = 0;yoffset = x;}
7260                         else {xoffset = x;yoffset = 0;}
7261                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7262                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7263                         // compute a texcoord array with the specified x and y offset
7264                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7265                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7266                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7267                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7268                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7269                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7270                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7271                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7272                         // this r value looks like a 'dot' particle, fading sharply to
7273                         // black at the edges
7274                         // (probably not realistic but looks good enough)
7275                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7276                         //r = brighten/(range*2+1);
7277                         r = brighten / (range * 2 + 1);
7278                         if(range >= 1)
7279                                 r *= (1 - x*x/(float)(range*range));
7280                         GL_Color(r, r, r, 1);
7281                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7282                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7283                         GL_BlendFunc(GL_ONE, GL_ONE);
7284                 }
7285
7286                 // copy the vertically blurred bloom view to a texture
7287                 GL_ActiveTexture(0);
7288                 CHECKGLERROR
7289                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7290                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7291         }
7292
7293         // apply subtract last
7294         // (just like it would be in a GLSL shader)
7295         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7296         {
7297                 GL_BlendFunc(GL_ONE, GL_ZERO);
7298                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7299                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7300                 GL_Color(1, 1, 1, 1);
7301                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7302                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7303
7304                 GL_BlendFunc(GL_ONE, GL_ONE);
7305                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7306                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7307                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7308                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7309                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7310                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7311                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7312
7313                 // copy the darkened bloom view to a texture
7314                 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);
7315                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7316         }
7317 }
7318
7319 void R_HDR_RenderBloomTexture(void)
7320 {
7321         int oldwidth, oldheight;
7322         float oldcolorscale;
7323
7324         oldcolorscale = r_refdef.view.colorscale;
7325         oldwidth = r_refdef.view.width;
7326         oldheight = r_refdef.view.height;
7327         r_refdef.view.width = r_bloomstate.bloomwidth;
7328         r_refdef.view.height = r_bloomstate.bloomheight;
7329
7330         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7331         // TODO: add exposure compensation features
7332         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7333
7334         r_refdef.view.showdebug = false;
7335         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7336
7337         R_ResetViewRendering3D();
7338
7339         R_ClearScreen(r_refdef.fogenabled);
7340         if (r_timereport_active)
7341                 R_TimeReport("HDRclear");
7342
7343         R_View_Update();
7344         if (r_timereport_active)
7345                 R_TimeReport("visibility");
7346
7347         // only do secondary renders with HDR if r_hdr is 2 or higher
7348         r_waterstate.numwaterplanes = 0;
7349         if (r_waterstate.enabled && r_hdr.integer >= 2)
7350                 R_RenderWaterPlanes();
7351
7352         r_refdef.view.showdebug = true;
7353         R_RenderScene();
7354         r_waterstate.numwaterplanes = 0;
7355
7356         R_ResetViewRendering2D();
7357
7358         R_Bloom_CopyHDRTexture();
7359         R_Bloom_MakeTexture();
7360
7361         // restore the view settings
7362         r_refdef.view.width = oldwidth;
7363         r_refdef.view.height = oldheight;
7364         r_refdef.view.colorscale = oldcolorscale;
7365
7366         R_ResetViewRendering3D();
7367
7368         R_ClearScreen(r_refdef.fogenabled);
7369         if (r_timereport_active)
7370                 R_TimeReport("viewclear");
7371 }
7372
7373 static void R_BlendView(void)
7374 {
7375         unsigned int permutation;
7376         float uservecs[4][4];
7377
7378         switch (vid.renderpath)
7379         {
7380         case RENDERPATH_GL20:
7381         case RENDERPATH_CGGL:
7382                 permutation =
7383                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7384                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7385                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7386                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7387                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7388
7389                 if (r_bloomstate.texture_screen)
7390                 {
7391                         // make sure the buffer is available
7392                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7393
7394                         R_ResetViewRendering2D();
7395                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7396                         R_Mesh_ColorPointer(NULL, 0, 0);
7397
7398                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7399                         {
7400                                 // declare variables
7401                                 float speed;
7402                                 static float avgspeed;
7403
7404                                 speed = VectorLength(cl.movement_velocity);
7405
7406                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7407                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7408
7409                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7410                                 speed = bound(0, speed, 1);
7411                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7412
7413                                 // calculate values into a standard alpha
7414                                 cl.motionbluralpha = 1 - exp(-
7415                                                 (
7416                                                  (r_motionblur.value * speed / 80)
7417                                                  +
7418                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7419                                                 )
7420                                                 /
7421                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7422                                            );
7423
7424                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7425                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7426                                 // apply the blur
7427                                 if (cl.motionbluralpha > 0)
7428                                 {
7429                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7430                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7431                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7432                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7433                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7434                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7435                                 }
7436                         }
7437
7438                         // copy view into the screen texture
7439                         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);
7440                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7441                 }
7442                 else if (!r_bloomstate.texture_bloom)
7443                 {
7444                         // we may still have to do view tint...
7445                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7446                         {
7447                                 // apply a color tint to the whole view
7448                                 R_ResetViewRendering2D();
7449                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7450                                 R_Mesh_ColorPointer(NULL, 0, 0);
7451                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7452                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7453                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7454                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7455                         }
7456                         break; // no screen processing, no bloom, skip it
7457                 }
7458
7459                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7460                 {
7461                         // render simple bloom effect
7462                         // copy the screen and shrink it and darken it for the bloom process
7463                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7464                         // make the bloom texture
7465                         R_Bloom_MakeTexture();
7466                 }
7467
7468 #if _MSC_VER >= 1400
7469 #define sscanf sscanf_s
7470 #endif
7471                 memset(uservecs, 0, sizeof(uservecs));
7472                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7473                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7474                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7475                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7476
7477                 R_ResetViewRendering2D();
7478                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7479                 R_Mesh_ColorPointer(NULL, 0, 0);
7480                 GL_Color(1, 1, 1, 1);
7481                 GL_BlendFunc(GL_ONE, GL_ZERO);
7482                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7483                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7484
7485                 switch(vid.renderpath)
7486                 {
7487                 case RENDERPATH_GL20:
7488                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7489                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7490                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7491                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7492                         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]);
7493                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7494                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7495                         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]);
7496                         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]);
7497                         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]);
7498                         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]);
7499                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7500                         break;
7501                 case RENDERPATH_CGGL:
7502 #ifdef SUPPORTCG
7503                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7504                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7505                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7506                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7507                         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
7508                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7509                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7510                         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
7511                         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
7512                         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
7513                         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
7514                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7515 #endif
7516                         break;
7517                 default:
7518                         break;
7519                 }
7520                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7521                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7522                 break;
7523         case RENDERPATH_GL13:
7524         case RENDERPATH_GL11:
7525                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7526                 {
7527                         // apply a color tint to the whole view
7528                         R_ResetViewRendering2D();
7529                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7530                         R_Mesh_ColorPointer(NULL, 0, 0);
7531                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7532                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7533                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7534                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7535                 }
7536                 break;
7537         }
7538 }
7539
7540 matrix4x4_t r_waterscrollmatrix;
7541
7542 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7543 {
7544         if (r_refdef.fog_density)
7545         {
7546                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7547                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7548                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7549
7550                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7551                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7552                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7553                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7554
7555                 {
7556                         vec3_t fogvec;
7557                         VectorCopy(r_refdef.fogcolor, fogvec);
7558                         //   color.rgb *= ContrastBoost * SceneBrightness;
7559                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7560                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7561                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7562                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7563                 }
7564         }
7565 }
7566
7567 void R_UpdateVariables(void)
7568 {
7569         R_Textures_Frame();
7570
7571         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7572
7573         r_refdef.farclip = r_farclip_base.value;
7574         if (r_refdef.scene.worldmodel)
7575                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7576         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7577
7578         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7579                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7580         r_refdef.polygonfactor = 0;
7581         r_refdef.polygonoffset = 0;
7582         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7583         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7584
7585         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7586         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7587         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7588         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7589         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7590         if (r_showsurfaces.integer)
7591         {
7592                 r_refdef.scene.rtworld = false;
7593                 r_refdef.scene.rtworldshadows = false;
7594                 r_refdef.scene.rtdlight = false;
7595                 r_refdef.scene.rtdlightshadows = false;
7596                 r_refdef.lightmapintensity = 0;
7597         }
7598
7599         if (gamemode == GAME_NEHAHRA)
7600         {
7601                 if (gl_fogenable.integer)
7602                 {
7603                         r_refdef.oldgl_fogenable = true;
7604                         r_refdef.fog_density = gl_fogdensity.value;
7605                         r_refdef.fog_red = gl_fogred.value;
7606                         r_refdef.fog_green = gl_foggreen.value;
7607                         r_refdef.fog_blue = gl_fogblue.value;
7608                         r_refdef.fog_alpha = 1;
7609                         r_refdef.fog_start = 0;
7610                         r_refdef.fog_end = gl_skyclip.value;
7611                         r_refdef.fog_height = 1<<30;
7612                         r_refdef.fog_fadedepth = 128;
7613                 }
7614                 else if (r_refdef.oldgl_fogenable)
7615                 {
7616                         r_refdef.oldgl_fogenable = false;
7617                         r_refdef.fog_density = 0;
7618                         r_refdef.fog_red = 0;
7619                         r_refdef.fog_green = 0;
7620                         r_refdef.fog_blue = 0;
7621                         r_refdef.fog_alpha = 0;
7622                         r_refdef.fog_start = 0;
7623                         r_refdef.fog_end = 0;
7624                         r_refdef.fog_height = 1<<30;
7625                         r_refdef.fog_fadedepth = 128;
7626                 }
7627         }
7628
7629         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7630         r_refdef.fog_start = max(0, r_refdef.fog_start);
7631         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7632
7633         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7634
7635         if (r_refdef.fog_density && r_drawfog.integer)
7636         {
7637                 r_refdef.fogenabled = true;
7638                 // this is the point where the fog reaches 0.9986 alpha, which we
7639                 // consider a good enough cutoff point for the texture
7640                 // (0.9986 * 256 == 255.6)
7641                 if (r_fog_exp2.integer)
7642                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7643                 else
7644                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7645                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7646                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7647                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7648                 // fog color was already set
7649                 // update the fog texture
7650                 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)
7651                         R_BuildFogTexture();
7652         }
7653         else
7654                 r_refdef.fogenabled = false;
7655
7656         switch(vid.renderpath)
7657         {
7658         case RENDERPATH_GL20:
7659         case RENDERPATH_CGGL:
7660                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7661                 {
7662                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7663                         {
7664                                 // build GLSL gamma texture
7665 #define RAMPWIDTH 256
7666                                 unsigned short ramp[RAMPWIDTH * 3];
7667                                 unsigned char rampbgr[RAMPWIDTH][4];
7668                                 int i;
7669
7670                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7671
7672                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7673                                 for(i = 0; i < RAMPWIDTH; ++i)
7674                                 {
7675                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7676                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7677                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7678                                         rampbgr[i][3] = 0;
7679                                 }
7680                                 if (r_texture_gammaramps)
7681                                 {
7682                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7683                                 }
7684                                 else
7685                                 {
7686                                         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);
7687                                 }
7688                         }
7689                 }
7690                 else
7691                 {
7692                         // remove GLSL gamma texture
7693                 }
7694                 break;
7695         case RENDERPATH_GL13:
7696         case RENDERPATH_GL11:
7697                 break;
7698         }
7699 }
7700
7701 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7702 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7703 /*
7704 ================
7705 R_SelectScene
7706 ================
7707 */
7708 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7709         if( scenetype != r_currentscenetype ) {
7710                 // store the old scenetype
7711                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7712                 r_currentscenetype = scenetype;
7713                 // move in the new scene
7714                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7715         }
7716 }
7717
7718 /*
7719 ================
7720 R_GetScenePointer
7721 ================
7722 */
7723 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7724 {
7725         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7726         if( scenetype == r_currentscenetype ) {
7727                 return &r_refdef.scene;
7728         } else {
7729                 return &r_scenes_store[ scenetype ];
7730         }
7731 }
7732
7733 /*
7734 ================
7735 R_RenderView
7736 ================
7737 */
7738 void R_RenderView(void)
7739 {
7740         if (r_timereport_active)
7741                 R_TimeReport("start");
7742         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7743
7744         if (!r_drawentities.integer)
7745                 r_refdef.scene.numentities = 0;
7746
7747         R_AnimCache_ClearCache();
7748         R_FrameData_NewFrame();
7749
7750         if (r_refdef.view.isoverlay)
7751         {
7752                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7753                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7754                 R_TimeReport("depthclear");
7755
7756                 r_refdef.view.showdebug = false;
7757
7758                 r_waterstate.enabled = false;
7759                 r_waterstate.numwaterplanes = 0;
7760
7761                 R_RenderScene();
7762
7763                 CHECKGLERROR
7764                 return;
7765         }
7766
7767         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7768                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7769
7770         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7771
7772         // break apart the view matrix into vectors for various purposes
7773         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7774         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7775         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7776         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7777         // make an inverted copy of the view matrix for tracking sprites
7778         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7779
7780         R_Shadow_UpdateWorldLightSelection();
7781
7782         R_Bloom_StartFrame();
7783         R_Water_StartFrame();
7784
7785         CHECKGLERROR
7786         if (r_timereport_active)
7787                 R_TimeReport("viewsetup");
7788
7789         R_ResetViewRendering3D();
7790
7791         if (r_refdef.view.clear || r_refdef.fogenabled)
7792         {
7793                 R_ClearScreen(r_refdef.fogenabled);
7794                 if (r_timereport_active)
7795                         R_TimeReport("viewclear");
7796         }
7797         r_refdef.view.clear = true;
7798
7799         // this produces a bloom texture to be used in R_BlendView() later
7800         if (r_hdr.integer && r_bloomstate.bloomwidth)
7801                 R_HDR_RenderBloomTexture();
7802
7803         r_refdef.view.showdebug = true;
7804
7805         R_View_Update();
7806         if (r_timereport_active)
7807                 R_TimeReport("visibility");
7808
7809         r_waterstate.numwaterplanes = 0;
7810         if (r_waterstate.enabled)
7811                 R_RenderWaterPlanes();
7812
7813         R_RenderScene();
7814         r_waterstate.numwaterplanes = 0;
7815
7816         R_BlendView();
7817         if (r_timereport_active)
7818                 R_TimeReport("blendview");
7819
7820         GL_Scissor(0, 0, vid.width, vid.height);
7821         GL_ScissorTest(false);
7822         CHECKGLERROR
7823 }
7824
7825 void R_RenderWaterPlanes(void)
7826 {
7827         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7828         {
7829                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7830                 if (r_timereport_active)
7831                         R_TimeReport("waterworld");
7832         }
7833
7834         // don't let sound skip if going slow
7835         if (r_refdef.scene.extraupdate)
7836                 S_ExtraUpdate ();
7837
7838         R_DrawModelsAddWaterPlanes();
7839         if (r_timereport_active)
7840                 R_TimeReport("watermodels");
7841
7842         if (r_waterstate.numwaterplanes)
7843         {
7844                 R_Water_ProcessPlanes();
7845                 if (r_timereport_active)
7846                         R_TimeReport("waterscenes");
7847         }
7848 }
7849
7850 extern void R_DrawLightningBeams (void);
7851 extern void VM_CL_AddPolygonsToMeshQueue (void);
7852 extern void R_DrawPortals (void);
7853 extern cvar_t cl_locs_show;
7854 static void R_DrawLocs(void);
7855 static void R_DrawEntityBBoxes(void);
7856 static void R_DrawModelDecals(void);
7857 extern cvar_t cl_decals_newsystem;
7858 extern qboolean r_shadow_usingdeferredprepass;
7859 void R_RenderScene(void)
7860 {
7861         r_refdef.stats.renders++;
7862         r_textureframe++; // used only by R_GetCurrentTexture
7863
7864         R_UpdateFogColor();
7865
7866         // don't let sound skip if going slow
7867         if (r_refdef.scene.extraupdate)
7868                 S_ExtraUpdate ();
7869
7870         R_MeshQueue_BeginScene();
7871
7872         R_SkyStartFrame();
7873
7874         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);
7875
7876         if (cl.csqc_vidvars.drawworld)
7877         {
7878                 // don't let sound skip if going slow
7879                 if (r_refdef.scene.extraupdate)
7880                         S_ExtraUpdate ();
7881
7882                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7883                 {
7884                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7885                         if (r_timereport_active)
7886                                 R_TimeReport("worldsky");
7887                 }
7888
7889                 if (R_DrawBrushModelsSky() && r_timereport_active)
7890                         R_TimeReport("bmodelsky");
7891
7892                 if (skyrendermasked && skyrenderlater)
7893                 {
7894                         // we have to force off the water clipping plane while rendering sky
7895                         R_SetupView(false);
7896                         R_Sky();
7897                         R_SetupView(true);
7898                         if (r_timereport_active)
7899                                 R_TimeReport("sky");
7900                 }
7901         }
7902
7903         R_AnimCache_CacheVisibleEntities();
7904         if (r_timereport_active)
7905                 R_TimeReport("animation");
7906
7907         R_Shadow_PrepareLights();
7908         if (r_timereport_active)
7909                 R_TimeReport("preparelights");
7910
7911         if (r_shadow_usingdeferredprepass)
7912                 R_Shadow_DrawPrepass();
7913
7914         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7915         {
7916                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7917                 if (r_timereport_active)
7918                         R_TimeReport("worlddepth");
7919         }
7920         if (r_depthfirst.integer >= 2)
7921         {
7922                 R_DrawModelsDepth();
7923                 if (r_timereport_active)
7924                         R_TimeReport("modeldepth");
7925         }
7926
7927         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7928         {
7929                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7930                 if (r_timereport_active)
7931                         R_TimeReport("world");
7932         }
7933
7934         // don't let sound skip if going slow
7935         if (r_refdef.scene.extraupdate)
7936                 S_ExtraUpdate ();
7937
7938         R_DrawModels();
7939         if (r_timereport_active)
7940                 R_TimeReport("models");
7941
7942         // don't let sound skip if going slow
7943         if (r_refdef.scene.extraupdate)
7944                 S_ExtraUpdate ();
7945
7946         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7947         {
7948                 R_DrawModelShadows();
7949                 R_ResetViewRendering3D();
7950                 // don't let sound skip if going slow
7951                 if (r_refdef.scene.extraupdate)
7952                         S_ExtraUpdate ();
7953         }
7954
7955         if (!r_shadow_usingdeferredprepass)
7956         {
7957                 R_Shadow_DrawLights();
7958                 if (r_timereport_active)
7959                         R_TimeReport("rtlights");
7960         }
7961
7962         // don't let sound skip if going slow
7963         if (r_refdef.scene.extraupdate)
7964                 S_ExtraUpdate ();
7965
7966         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7967         {
7968                 R_DrawModelShadows();
7969                 R_ResetViewRendering3D();
7970                 // don't let sound skip if going slow
7971                 if (r_refdef.scene.extraupdate)
7972                         S_ExtraUpdate ();
7973         }
7974
7975         if (cl.csqc_vidvars.drawworld)
7976         {
7977                 if (cl_decals_newsystem.integer)
7978                 {
7979                         R_DrawModelDecals();
7980                         if (r_timereport_active)
7981                                 R_TimeReport("modeldecals");
7982                 }
7983                 else
7984                 {
7985                         R_DrawDecals();
7986                         if (r_timereport_active)
7987                                 R_TimeReport("decals");
7988                 }
7989
7990                 R_DrawParticles();
7991                 if (r_timereport_active)
7992                         R_TimeReport("particles");
7993
7994                 R_DrawExplosions();
7995                 if (r_timereport_active)
7996                         R_TimeReport("explosions");
7997
7998                 R_DrawLightningBeams();
7999                 if (r_timereport_active)
8000                         R_TimeReport("lightning");
8001         }
8002
8003         VM_CL_AddPolygonsToMeshQueue();
8004
8005         if (r_refdef.view.showdebug)
8006         {
8007                 if (cl_locs_show.integer)
8008                 {
8009                         R_DrawLocs();
8010                         if (r_timereport_active)
8011                                 R_TimeReport("showlocs");
8012                 }
8013
8014                 if (r_drawportals.integer)
8015                 {
8016                         R_DrawPortals();
8017                         if (r_timereport_active)
8018                                 R_TimeReport("portals");
8019                 }
8020
8021                 if (r_showbboxes.value > 0)
8022                 {
8023                         R_DrawEntityBBoxes();
8024                         if (r_timereport_active)
8025                                 R_TimeReport("bboxes");
8026                 }
8027         }
8028
8029         R_MeshQueue_RenderTransparent();
8030         if (r_timereport_active)
8031                 R_TimeReport("drawtrans");
8032
8033         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))
8034         {
8035                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8036                 if (r_timereport_active)
8037                         R_TimeReport("worlddebug");
8038                 R_DrawModelsDebug();
8039                 if (r_timereport_active)
8040                         R_TimeReport("modeldebug");
8041         }
8042
8043         if (cl.csqc_vidvars.drawworld)
8044         {
8045                 R_Shadow_DrawCoronas();
8046                 if (r_timereport_active)
8047                         R_TimeReport("coronas");
8048         }
8049
8050         // don't let sound skip if going slow
8051         if (r_refdef.scene.extraupdate)
8052                 S_ExtraUpdate ();
8053
8054         R_ResetViewRendering2D();
8055 }
8056
8057 static const unsigned short bboxelements[36] =
8058 {
8059         5, 1, 3, 5, 3, 7,
8060         6, 2, 0, 6, 0, 4,
8061         7, 3, 2, 7, 2, 6,
8062         4, 0, 1, 4, 1, 5,
8063         4, 5, 7, 4, 7, 6,
8064         1, 0, 2, 1, 2, 3,
8065 };
8066
8067 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8068 {
8069         int i;
8070         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8071
8072         RSurf_ActiveWorldEntity();
8073
8074         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8075         GL_DepthMask(false);
8076         GL_DepthRange(0, 1);
8077         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8078         R_Mesh_ResetTextureState();
8079
8080         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8081         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8082         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8083         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8084         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8085         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8086         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8087         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8088         R_FillColors(color4f, 8, cr, cg, cb, ca);
8089         if (r_refdef.fogenabled)
8090         {
8091                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8092                 {
8093                         f1 = RSurf_FogVertex(v);
8094                         f2 = 1 - f1;
8095                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8096                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8097                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8098                 }
8099         }
8100         R_Mesh_VertexPointer(vertex3f, 0, 0);
8101         R_Mesh_ColorPointer(color4f, 0, 0);
8102         R_Mesh_ResetTextureState();
8103         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8104         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8105 }
8106
8107 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8108 {
8109         int i;
8110         float color[4];
8111         prvm_edict_t *edict;
8112         prvm_prog_t *prog_save = prog;
8113
8114         // this function draws bounding boxes of server entities
8115         if (!sv.active)
8116                 return;
8117
8118         GL_CullFace(GL_NONE);
8119         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8120
8121         prog = 0;
8122         SV_VM_Begin();
8123         for (i = 0;i < numsurfaces;i++)
8124         {
8125                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8126                 switch ((int)edict->fields.server->solid)
8127                 {
8128                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8129                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8130                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8131                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8132                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8133                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8134                 }
8135                 color[3] *= r_showbboxes.value;
8136                 color[3] = bound(0, color[3], 1);
8137                 GL_DepthTest(!r_showdisabledepthtest.integer);
8138                 GL_CullFace(r_refdef.view.cullface_front);
8139                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8140         }
8141         SV_VM_End();
8142         prog = prog_save;
8143 }
8144
8145 static void R_DrawEntityBBoxes(void)
8146 {
8147         int i;
8148         prvm_edict_t *edict;
8149         vec3_t center;
8150         prvm_prog_t *prog_save = prog;
8151
8152         // this function draws bounding boxes of server entities
8153         if (!sv.active)
8154                 return;
8155
8156         prog = 0;
8157         SV_VM_Begin();
8158         for (i = 0;i < prog->num_edicts;i++)
8159         {
8160                 edict = PRVM_EDICT_NUM(i);
8161                 if (edict->priv.server->free)
8162                         continue;
8163                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8164                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8165                         continue;
8166                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8167                         continue;
8168                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8169                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8170         }
8171         SV_VM_End();
8172         prog = prog_save;
8173 }
8174
8175 static const int nomodelelement3i[24] =
8176 {
8177         5, 2, 0,
8178         5, 1, 2,
8179         5, 0, 3,
8180         5, 3, 1,
8181         0, 2, 4,
8182         2, 1, 4,
8183         3, 0, 4,
8184         1, 3, 4
8185 };
8186
8187 static const unsigned short nomodelelement3s[24] =
8188 {
8189         5, 2, 0,
8190         5, 1, 2,
8191         5, 0, 3,
8192         5, 3, 1,
8193         0, 2, 4,
8194         2, 1, 4,
8195         3, 0, 4,
8196         1, 3, 4
8197 };
8198
8199 static const float nomodelvertex3f[6*3] =
8200 {
8201         -16,   0,   0,
8202          16,   0,   0,
8203           0, -16,   0,
8204           0,  16,   0,
8205           0,   0, -16,
8206           0,   0,  16
8207 };
8208
8209 static const float nomodelcolor4f[6*4] =
8210 {
8211         0.0f, 0.0f, 0.5f, 1.0f,
8212         0.0f, 0.0f, 0.5f, 1.0f,
8213         0.0f, 0.5f, 0.0f, 1.0f,
8214         0.0f, 0.5f, 0.0f, 1.0f,
8215         0.5f, 0.0f, 0.0f, 1.0f,
8216         0.5f, 0.0f, 0.0f, 1.0f
8217 };
8218
8219 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8220 {
8221         int i;
8222         float f1, f2, *c;
8223         float color4f[6*4];
8224
8225         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);
8226
8227         // this is only called once per entity so numsurfaces is always 1, and
8228         // surfacelist is always {0}, so this code does not handle batches
8229
8230         if (rsurface.ent_flags & RENDER_ADDITIVE)
8231         {
8232                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8233                 GL_DepthMask(false);
8234         }
8235         else if (rsurface.colormod[3] < 1)
8236         {
8237                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8238                 GL_DepthMask(false);
8239         }
8240         else
8241         {
8242                 GL_BlendFunc(GL_ONE, GL_ZERO);
8243                 GL_DepthMask(true);
8244         }
8245         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8246         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8247         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8248         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8249         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8250         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8251         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8252         R_Mesh_ColorPointer(color4f, 0, 0);
8253         for (i = 0, c = color4f;i < 6;i++, c += 4)
8254         {
8255                 c[0] *= rsurface.colormod[0];
8256                 c[1] *= rsurface.colormod[1];
8257                 c[2] *= rsurface.colormod[2];
8258                 c[3] *= rsurface.colormod[3];
8259         }
8260         if (r_refdef.fogenabled)
8261         {
8262                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8263                 {
8264                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8265                         f2 = 1 - f1;
8266                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8267                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8268                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8269                 }
8270         }
8271         R_Mesh_ResetTextureState();
8272         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8273 }
8274
8275 void R_DrawNoModel(entity_render_t *ent)
8276 {
8277         vec3_t org;
8278         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8279         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8280                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8281         else
8282                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8283 }
8284
8285 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8286 {
8287         vec3_t right1, right2, diff, normal;
8288
8289         VectorSubtract (org2, org1, normal);
8290
8291         // calculate 'right' vector for start
8292         VectorSubtract (r_refdef.view.origin, org1, diff);
8293         CrossProduct (normal, diff, right1);
8294         VectorNormalize (right1);
8295
8296         // calculate 'right' vector for end
8297         VectorSubtract (r_refdef.view.origin, org2, diff);
8298         CrossProduct (normal, diff, right2);
8299         VectorNormalize (right2);
8300
8301         vert[ 0] = org1[0] + width * right1[0];
8302         vert[ 1] = org1[1] + width * right1[1];
8303         vert[ 2] = org1[2] + width * right1[2];
8304         vert[ 3] = org1[0] - width * right1[0];
8305         vert[ 4] = org1[1] - width * right1[1];
8306         vert[ 5] = org1[2] - width * right1[2];
8307         vert[ 6] = org2[0] - width * right2[0];
8308         vert[ 7] = org2[1] - width * right2[1];
8309         vert[ 8] = org2[2] - width * right2[2];
8310         vert[ 9] = org2[0] + width * right2[0];
8311         vert[10] = org2[1] + width * right2[1];
8312         vert[11] = org2[2] + width * right2[2];
8313 }
8314
8315 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)
8316 {
8317         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8318         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8319         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8320         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8321         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8322         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8323         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8324         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8325         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8326         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8327         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8328         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8329 }
8330
8331 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8332 {
8333         int i;
8334         float *vertex3f;
8335         float v[3];
8336         VectorSet(v, x, y, z);
8337         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8338                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8339                         break;
8340         if (i == mesh->numvertices)
8341         {
8342                 if (mesh->numvertices < mesh->maxvertices)
8343                 {
8344                         VectorCopy(v, vertex3f);
8345                         mesh->numvertices++;
8346                 }
8347                 return mesh->numvertices;
8348         }
8349         else
8350                 return i;
8351 }
8352
8353 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8354 {
8355         int i;
8356         int *e, element[3];
8357         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8358         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8359         e = mesh->element3i + mesh->numtriangles * 3;
8360         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8361         {
8362                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8363                 if (mesh->numtriangles < mesh->maxtriangles)
8364                 {
8365                         *e++ = element[0];
8366                         *e++ = element[1];
8367                         *e++ = element[2];
8368                         mesh->numtriangles++;
8369                 }
8370                 element[1] = element[2];
8371         }
8372 }
8373
8374 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8375 {
8376         int i;
8377         int *e, element[3];
8378         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8379         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8380         e = mesh->element3i + mesh->numtriangles * 3;
8381         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8382         {
8383                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8384                 if (mesh->numtriangles < mesh->maxtriangles)
8385                 {
8386                         *e++ = element[0];
8387                         *e++ = element[1];
8388                         *e++ = element[2];
8389                         mesh->numtriangles++;
8390                 }
8391                 element[1] = element[2];
8392         }
8393 }
8394
8395 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8396 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8397 {
8398         int planenum, planenum2;
8399         int w;
8400         int tempnumpoints;
8401         mplane_t *plane, *plane2;
8402         double maxdist;
8403         double temppoints[2][256*3];
8404         // figure out how large a bounding box we need to properly compute this brush
8405         maxdist = 0;
8406         for (w = 0;w < numplanes;w++)
8407                 maxdist = max(maxdist, fabs(planes[w].dist));
8408         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8409         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8410         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8411         {
8412                 w = 0;
8413                 tempnumpoints = 4;
8414                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8415                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8416                 {
8417                         if (planenum2 == planenum)
8418                                 continue;
8419                         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);
8420                         w = !w;
8421                 }
8422                 if (tempnumpoints < 3)
8423                         continue;
8424                 // generate elements forming a triangle fan for this polygon
8425                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8426         }
8427 }
8428
8429 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)
8430 {
8431         texturelayer_t *layer;
8432         layer = t->currentlayers + t->currentnumlayers++;
8433         layer->type = type;
8434         layer->depthmask = depthmask;
8435         layer->blendfunc1 = blendfunc1;
8436         layer->blendfunc2 = blendfunc2;
8437         layer->texture = texture;
8438         layer->texmatrix = *matrix;
8439         layer->color[0] = r;
8440         layer->color[1] = g;
8441         layer->color[2] = b;
8442         layer->color[3] = a;
8443 }
8444
8445 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8446 {
8447         double index, f;
8448         index = parms[2] + r_refdef.scene.time * parms[3];
8449         index -= floor(index);
8450         switch (func)
8451         {
8452         default:
8453         case Q3WAVEFUNC_NONE:
8454         case Q3WAVEFUNC_NOISE:
8455         case Q3WAVEFUNC_COUNT:
8456                 f = 0;
8457                 break;
8458         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8459         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8460         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8461         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8462         case Q3WAVEFUNC_TRIANGLE:
8463                 index *= 4;
8464                 f = index - floor(index);
8465                 if (index < 1)
8466                         f = f;
8467                 else if (index < 2)
8468                         f = 1 - f;
8469                 else if (index < 3)
8470                         f = -f;
8471                 else
8472                         f = -(1 - f);
8473                 break;
8474         }
8475         return (float)(parms[0] + parms[1] * f);
8476 }
8477
8478 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8479 {
8480         int w, h, idx;
8481         float f;
8482         float tcmat[12];
8483         matrix4x4_t matrix, temp;
8484         switch(tcmod->tcmod)
8485         {
8486                 case Q3TCMOD_COUNT:
8487                 case Q3TCMOD_NONE:
8488                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8489                                 matrix = r_waterscrollmatrix;
8490                         else
8491                                 matrix = identitymatrix;
8492                         break;
8493                 case Q3TCMOD_ENTITYTRANSLATE:
8494                         // this is used in Q3 to allow the gamecode to control texcoord
8495                         // scrolling on the entity, which is not supported in darkplaces yet.
8496                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8497                         break;
8498                 case Q3TCMOD_ROTATE:
8499                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8500                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8501                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8502                         break;
8503                 case Q3TCMOD_SCALE:
8504                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8505                         break;
8506                 case Q3TCMOD_SCROLL:
8507                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8508                         break;
8509                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8510                         w = (int) tcmod->parms[0];
8511                         h = (int) tcmod->parms[1];
8512                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8513                         f = f - floor(f);
8514                         idx = (int) floor(f * w * h);
8515                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8516                         break;
8517                 case Q3TCMOD_STRETCH:
8518                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8519                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8520                         break;
8521                 case Q3TCMOD_TRANSFORM:
8522                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8523                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8524                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8525                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8526                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8527                         break;
8528                 case Q3TCMOD_TURBULENT:
8529                         // this is handled in the RSurf_PrepareVertices function
8530                         matrix = identitymatrix;
8531                         break;
8532         }
8533         temp = *texmatrix;
8534         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8535 }
8536
8537 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8538 {
8539         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8540         char name[MAX_QPATH];
8541         skinframe_t *skinframe;
8542         unsigned char pixels[296*194];
8543         strlcpy(cache->name, skinname, sizeof(cache->name));
8544         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8545         if (developer_loading.integer)
8546                 Con_Printf("loading %s\n", name);
8547         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8548         if (!skinframe || !skinframe->base)
8549         {
8550                 unsigned char *f;
8551                 fs_offset_t filesize;
8552                 skinframe = NULL;
8553                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8554                 if (f)
8555                 {
8556                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8557                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8558                         Mem_Free(f);
8559                 }
8560         }
8561         cache->skinframe = skinframe;
8562 }
8563
8564 texture_t *R_GetCurrentTexture(texture_t *t)
8565 {
8566         int i;
8567         const entity_render_t *ent = rsurface.entity;
8568         dp_model_t *model = ent->model;
8569         q3shaderinfo_layer_tcmod_t *tcmod;
8570
8571         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8572                 return t->currentframe;
8573         t->update_lastrenderframe = r_textureframe;
8574         t->update_lastrenderentity = (void *)ent;
8575
8576         // switch to an alternate material if this is a q1bsp animated material
8577         {
8578                 texture_t *texture = t;
8579                 int s = rsurface.ent_skinnum;
8580                 if ((unsigned int)s >= (unsigned int)model->numskins)
8581                         s = 0;
8582                 if (model->skinscenes)
8583                 {
8584                         if (model->skinscenes[s].framecount > 1)
8585                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8586                         else
8587                                 s = model->skinscenes[s].firstframe;
8588                 }
8589                 if (s > 0)
8590                         t = t + s * model->num_surfaces;
8591                 if (t->animated)
8592                 {
8593                         // use an alternate animation if the entity's frame is not 0,
8594                         // and only if the texture has an alternate animation
8595                         if (rsurface.ent_alttextures && t->anim_total[1])
8596                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8597                         else
8598                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8599                 }
8600                 texture->currentframe = t;
8601         }
8602
8603         // update currentskinframe to be a qw skin or animation frame
8604         if (rsurface.ent_qwskin >= 0)
8605         {
8606                 i = rsurface.ent_qwskin;
8607                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8608                 {
8609                         r_qwskincache_size = cl.maxclients;
8610                         if (r_qwskincache)
8611                                 Mem_Free(r_qwskincache);
8612                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8613                 }
8614                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8615                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8616                 t->currentskinframe = r_qwskincache[i].skinframe;
8617                 if (t->currentskinframe == NULL)
8618                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8619         }
8620         else if (t->numskinframes >= 2)
8621                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8622         if (t->backgroundnumskinframes >= 2)
8623                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8624
8625         t->currentmaterialflags = t->basematerialflags;
8626         t->currentalpha = rsurface.colormod[3];
8627         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8628                 t->currentalpha *= r_wateralpha.value;
8629         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8630                 t->currentalpha *= t->r_water_wateralpha;
8631         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8632                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8633         if (!(rsurface.ent_flags & RENDER_LIGHT))
8634                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8635         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8636         {
8637                 // pick a model lighting mode
8638                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8639                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8640                 else
8641                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8642         }
8643         if (rsurface.ent_flags & RENDER_ADDITIVE)
8644                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8645         else if (t->currentalpha < 1)
8646                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8647         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8648                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8649         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8650                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8651         if (t->backgroundnumskinframes)
8652                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8653         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8654         {
8655                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8656                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8657         }
8658         else
8659                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8660         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8661                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8662
8663         // there is no tcmod
8664         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8665         {
8666                 t->currenttexmatrix = r_waterscrollmatrix;
8667                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8668         }
8669         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8670         {
8671                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8672                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8673         }
8674
8675         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8676                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8677         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8678                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8679
8680         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8681         if (t->currentskinframe->qpixels)
8682                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8683         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8684         if (!t->basetexture)
8685                 t->basetexture = r_texture_notexture;
8686         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8687         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8688         t->nmaptexture = t->currentskinframe->nmap;
8689         if (!t->nmaptexture)
8690                 t->nmaptexture = r_texture_blanknormalmap;
8691         t->glosstexture = r_texture_black;
8692         t->glowtexture = t->currentskinframe->glow;
8693         t->fogtexture = t->currentskinframe->fog;
8694         if (t->backgroundnumskinframes)
8695         {
8696                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8697                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8698                 t->backgroundglosstexture = r_texture_black;
8699                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8700                 if (!t->backgroundnmaptexture)
8701                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8702         }
8703         else
8704         {
8705                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8706                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8707                 t->backgroundglosstexture = r_texture_black;
8708                 t->backgroundglowtexture = NULL;
8709         }
8710         t->specularpower = r_shadow_glossexponent.value;
8711         // TODO: store reference values for these in the texture?
8712         t->specularscale = 0;
8713         if (r_shadow_gloss.integer > 0)
8714         {
8715                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8716                 {
8717                         if (r_shadow_glossintensity.value > 0)
8718                         {
8719                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8720                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8721                                 t->specularscale = r_shadow_glossintensity.value;
8722                         }
8723                 }
8724                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8725                 {
8726                         t->glosstexture = r_texture_white;
8727                         t->backgroundglosstexture = r_texture_white;
8728                         t->specularscale = r_shadow_gloss2intensity.value;
8729                         t->specularpower = r_shadow_gloss2exponent.value;
8730                 }
8731         }
8732         t->specularscale *= t->specularscalemod;
8733         t->specularpower *= t->specularpowermod;
8734
8735         // lightmaps mode looks bad with dlights using actual texturing, so turn
8736         // off the colormap and glossmap, but leave the normalmap on as it still
8737         // accurately represents the shading involved
8738         if (gl_lightmaps.integer)
8739         {
8740                 t->basetexture = r_texture_grey128;
8741                 t->pantstexture = r_texture_black;
8742                 t->shirttexture = r_texture_black;
8743                 t->nmaptexture = r_texture_blanknormalmap;
8744                 t->glosstexture = r_texture_black;
8745                 t->glowtexture = NULL;
8746                 t->fogtexture = NULL;
8747                 t->backgroundbasetexture = NULL;
8748                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8749                 t->backgroundglosstexture = r_texture_black;
8750                 t->backgroundglowtexture = NULL;
8751                 t->specularscale = 0;
8752                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8753         }
8754
8755         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8756         VectorClear(t->dlightcolor);
8757         t->currentnumlayers = 0;
8758         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8759         {
8760                 int blendfunc1, blendfunc2;
8761                 qboolean depthmask;
8762                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8763                 {
8764                         blendfunc1 = GL_SRC_ALPHA;
8765                         blendfunc2 = GL_ONE;
8766                 }
8767                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8768                 {
8769                         blendfunc1 = GL_SRC_ALPHA;
8770                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8771                 }
8772                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8773                 {
8774                         blendfunc1 = t->customblendfunc[0];
8775                         blendfunc2 = t->customblendfunc[1];
8776                 }
8777                 else
8778                 {
8779                         blendfunc1 = GL_ONE;
8780                         blendfunc2 = GL_ZERO;
8781                 }
8782                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8783                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8784                 {
8785                         // fullbright is not affected by r_refdef.lightmapintensity
8786                         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]);
8787                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8788                                 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]);
8789                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8790                                 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]);
8791                 }
8792                 else
8793                 {
8794                         vec3_t ambientcolor;
8795                         float colorscale;
8796                         // set the color tint used for lights affecting this surface
8797                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8798                         colorscale = 2;
8799                         // q3bsp has no lightmap updates, so the lightstylevalue that
8800                         // would normally be baked into the lightmap must be
8801                         // applied to the color
8802                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8803                         if (model->type == mod_brushq3)
8804                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8805                         colorscale *= r_refdef.lightmapintensity;
8806                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8807                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8808                         // basic lit geometry
8809                         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]);
8810                         // add pants/shirt if needed
8811                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8812                                 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]);
8813                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8814                                 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]);
8815                         // now add ambient passes if needed
8816                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8817                         {
8818                                 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]);
8819                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8820                                         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]);
8821                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8822                                         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]);
8823                         }
8824                 }
8825                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8826                         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]);
8827                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8828                 {
8829                         // if this is opaque use alpha blend which will darken the earlier
8830                         // passes cheaply.
8831                         //
8832                         // if this is an alpha blended material, all the earlier passes
8833                         // were darkened by fog already, so we only need to add the fog
8834                         // color ontop through the fog mask texture
8835                         //
8836                         // if this is an additive blended material, all the earlier passes
8837                         // were darkened by fog already, and we should not add fog color
8838                         // (because the background was not darkened, there is no fog color
8839                         // that was lost behind it).
8840                         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]);
8841                 }
8842         }
8843
8844         return t->currentframe;
8845 }
8846
8847 rsurfacestate_t rsurface;
8848
8849 void R_Mesh_ResizeArrays(int newvertices)
8850 {
8851         float *base;
8852         if (rsurface.array_size >= newvertices)
8853                 return;
8854         if (rsurface.array_modelvertex3f)
8855                 Mem_Free(rsurface.array_modelvertex3f);
8856         rsurface.array_size = (newvertices + 1023) & ~1023;
8857         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8858         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8859         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8860         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8861         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8862         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8863         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8864         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8865         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8866         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8867         rsurface.array_color4f           = base + rsurface.array_size * 27;
8868         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8869 }
8870
8871 void RSurf_ActiveWorldEntity(void)
8872 {
8873         dp_model_t *model = r_refdef.scene.worldmodel;
8874         //if (rsurface.entity == r_refdef.scene.worldentity)
8875         //      return;
8876         rsurface.entity = r_refdef.scene.worldentity;
8877         rsurface.skeleton = NULL;
8878         rsurface.ent_skinnum = 0;
8879         rsurface.ent_qwskin = -1;
8880         rsurface.ent_shadertime = 0;
8881         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8882         if (rsurface.array_size < model->surfmesh.num_vertices)
8883                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8884         rsurface.matrix = identitymatrix;
8885         rsurface.inversematrix = identitymatrix;
8886         rsurface.matrixscale = 1;
8887         rsurface.inversematrixscale = 1;
8888         R_EntityMatrix(&identitymatrix);
8889         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8890         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8891         rsurface.fograngerecip = r_refdef.fograngerecip;
8892         rsurface.fogheightfade = r_refdef.fogheightfade;
8893         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8894         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8895         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8896         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8897         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8898         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8899         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8900         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8901         rsurface.colormod[3] = 1;
8902         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);
8903         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8904         rsurface.frameblend[0].lerp = 1;
8905         rsurface.ent_alttextures = false;
8906         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8907         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8908         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8909         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8910         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8911         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8912         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8913         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8914         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8915         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8916         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8917         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8918         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8919         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8920         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8921         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8922         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8923         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8924         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8925         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8926         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8927         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8928         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8929         rsurface.modelelement3i = model->surfmesh.data_element3i;
8930         rsurface.modelelement3s = model->surfmesh.data_element3s;
8931         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8932         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8933         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8934         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8935         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8936         rsurface.modelsurfaces = model->data_surfaces;
8937         rsurface.generatedvertex = false;
8938         rsurface.vertex3f  = rsurface.modelvertex3f;
8939         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8940         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8941         rsurface.svector3f = rsurface.modelsvector3f;
8942         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8943         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8944         rsurface.tvector3f = rsurface.modeltvector3f;
8945         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8946         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8947         rsurface.normal3f  = rsurface.modelnormal3f;
8948         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8949         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8950         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8951 }
8952
8953 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8954 {
8955         dp_model_t *model = ent->model;
8956         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8957         //      return;
8958         rsurface.entity = (entity_render_t *)ent;
8959         rsurface.skeleton = ent->skeleton;
8960         rsurface.ent_skinnum = ent->skinnum;
8961         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;
8962         rsurface.ent_shadertime = ent->shadertime;
8963         rsurface.ent_flags = ent->flags;
8964         if (rsurface.array_size < model->surfmesh.num_vertices)
8965                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8966         rsurface.matrix = ent->matrix;
8967         rsurface.inversematrix = ent->inversematrix;
8968         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8969         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8970         R_EntityMatrix(&rsurface.matrix);
8971         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8972         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8973         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8974         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8975         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8976         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8977         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8978         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8979         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8980         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8981         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8982         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8983         rsurface.colormod[3] = ent->alpha;
8984         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8985         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8986         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8987         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8988         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8989         if (ent->model->brush.submodel && !prepass)
8990         {
8991                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8992                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8993         }
8994         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8995         {
8996                 if (ent->animcache_vertex3f && !r_framedata_failed)
8997                 {
8998                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8999                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9000                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9001                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9002                 }
9003                 else if (wanttangents)
9004                 {
9005                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9006                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9007                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9008                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9009                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9010                 }
9011                 else if (wantnormals)
9012                 {
9013                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9014                         rsurface.modelsvector3f = NULL;
9015                         rsurface.modeltvector3f = NULL;
9016                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9017                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9018                 }
9019                 else
9020                 {
9021                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9022                         rsurface.modelsvector3f = NULL;
9023                         rsurface.modeltvector3f = NULL;
9024                         rsurface.modelnormal3f = NULL;
9025                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9026                 }
9027                 rsurface.modelvertex3f_bufferobject = 0;
9028                 rsurface.modelvertex3f_bufferoffset = 0;
9029                 rsurface.modelsvector3f_bufferobject = 0;
9030                 rsurface.modelsvector3f_bufferoffset = 0;
9031                 rsurface.modeltvector3f_bufferobject = 0;
9032                 rsurface.modeltvector3f_bufferoffset = 0;
9033                 rsurface.modelnormal3f_bufferobject = 0;
9034                 rsurface.modelnormal3f_bufferoffset = 0;
9035                 rsurface.generatedvertex = true;
9036         }
9037         else
9038         {
9039                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9040                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9041                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9042                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9043                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9044                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9045                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9046                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9047                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9048                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9049                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9050                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9051                 rsurface.generatedvertex = false;
9052         }
9053         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9054         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9055         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9056         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9057         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9058         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9059         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9060         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9061         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9062         rsurface.modelelement3i = model->surfmesh.data_element3i;
9063         rsurface.modelelement3s = model->surfmesh.data_element3s;
9064         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9065         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9066         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9067         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9068         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9069         rsurface.modelsurfaces = model->data_surfaces;
9070         rsurface.vertex3f  = rsurface.modelvertex3f;
9071         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9072         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9073         rsurface.svector3f = rsurface.modelsvector3f;
9074         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9075         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9076         rsurface.tvector3f = rsurface.modeltvector3f;
9077         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9078         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9079         rsurface.normal3f  = rsurface.modelnormal3f;
9080         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9081         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9082         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9083 }
9084
9085 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)
9086 {
9087         rsurface.entity = r_refdef.scene.worldentity;
9088         rsurface.skeleton = NULL;
9089         rsurface.ent_skinnum = 0;
9090         rsurface.ent_qwskin = -1;
9091         rsurface.ent_shadertime = shadertime;
9092         rsurface.ent_flags = entflags;
9093         rsurface.modelnum_vertices = numvertices;
9094         rsurface.modelnum_triangles = numtriangles;
9095         if (rsurface.array_size < rsurface.modelnum_vertices)
9096                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9097         rsurface.matrix = *matrix;
9098         rsurface.inversematrix = *inversematrix;
9099         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9100         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9101         R_EntityMatrix(&rsurface.matrix);
9102         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9103         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9104         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9105         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9106         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9107         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9108         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9109         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9110         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9111         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9112         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9113         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9114         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);
9115         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9116         rsurface.frameblend[0].lerp = 1;
9117         rsurface.ent_alttextures = false;
9118         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9119         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9120         if (wanttangents)
9121         {
9122                 rsurface.modelvertex3f = vertex3f;
9123                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9124                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9125                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9126         }
9127         else if (wantnormals)
9128         {
9129                 rsurface.modelvertex3f = vertex3f;
9130                 rsurface.modelsvector3f = NULL;
9131                 rsurface.modeltvector3f = NULL;
9132                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9133         }
9134         else
9135         {
9136                 rsurface.modelvertex3f = vertex3f;
9137                 rsurface.modelsvector3f = NULL;
9138                 rsurface.modeltvector3f = NULL;
9139                 rsurface.modelnormal3f = NULL;
9140         }
9141         rsurface.modelvertex3f_bufferobject = 0;
9142         rsurface.modelvertex3f_bufferoffset = 0;
9143         rsurface.modelsvector3f_bufferobject = 0;
9144         rsurface.modelsvector3f_bufferoffset = 0;
9145         rsurface.modeltvector3f_bufferobject = 0;
9146         rsurface.modeltvector3f_bufferoffset = 0;
9147         rsurface.modelnormal3f_bufferobject = 0;
9148         rsurface.modelnormal3f_bufferoffset = 0;
9149         rsurface.generatedvertex = true;
9150         rsurface.modellightmapcolor4f  = color4f;
9151         rsurface.modellightmapcolor4f_bufferobject = 0;
9152         rsurface.modellightmapcolor4f_bufferoffset = 0;
9153         rsurface.modeltexcoordtexture2f  = texcoord2f;
9154         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9155         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9156         rsurface.modeltexcoordlightmap2f  = NULL;
9157         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9158         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9159         rsurface.modelelement3i = element3i;
9160         rsurface.modelelement3s = element3s;
9161         rsurface.modelelement3i_bufferobject = 0;
9162         rsurface.modelelement3s_bufferobject = 0;
9163         rsurface.modellightmapoffsets = NULL;
9164         rsurface.modelsurfaces = NULL;
9165         rsurface.vertex3f  = rsurface.modelvertex3f;
9166         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9167         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9168         rsurface.svector3f = rsurface.modelsvector3f;
9169         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9170         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9171         rsurface.tvector3f = rsurface.modeltvector3f;
9172         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9173         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9174         rsurface.normal3f  = rsurface.modelnormal3f;
9175         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9176         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9177         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9178
9179         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9180         {
9181                 if ((wantnormals || wanttangents) && !normal3f)
9182                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9183                 if (wanttangents && !svector3f)
9184                         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);
9185         }
9186 }
9187
9188 float RSurf_FogPoint(const float *v)
9189 {
9190         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9191         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9192         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9193         float FogHeightFade = r_refdef.fogheightfade;
9194         float fogfrac;
9195         unsigned int fogmasktableindex;
9196         if (r_refdef.fogplaneviewabove)
9197                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9198         else
9199                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9200         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9201         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9202 }
9203
9204 float RSurf_FogVertex(const float *v)
9205 {
9206         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9207         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9208         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9209         float FogHeightFade = rsurface.fogheightfade;
9210         float fogfrac;
9211         unsigned int fogmasktableindex;
9212         if (r_refdef.fogplaneviewabove)
9213                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9214         else
9215                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9216         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9217         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9218 }
9219
9220 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9221 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9222 {
9223         int deformindex;
9224         int texturesurfaceindex;
9225         int i, j;
9226         float amplitude;
9227         float animpos;
9228         float scale;
9229         const float *v1, *in_tc;
9230         float *out_tc;
9231         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9232         float waveparms[4];
9233         q3shaderinfo_deform_t *deform;
9234         // 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
9235         if (rsurface.generatedvertex)
9236         {
9237                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9238                         generatenormals = true;
9239                 for (i = 0;i < Q3MAXDEFORMS;i++)
9240                 {
9241                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9242                         {
9243                                 generatetangents = true;
9244                                 generatenormals = true;
9245                         }
9246                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9247                                 generatenormals = true;
9248                 }
9249                 if (generatenormals && !rsurface.modelnormal3f)
9250                 {
9251                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9252                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9253                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9254                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9255                 }
9256                 if (generatetangents && !rsurface.modelsvector3f)
9257                 {
9258                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9259                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9260                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9261                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9262                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9263                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9264                         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);
9265                 }
9266         }
9267         rsurface.vertex3f  = rsurface.modelvertex3f;
9268         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9269         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9270         rsurface.svector3f = rsurface.modelsvector3f;
9271         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9272         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9273         rsurface.tvector3f = rsurface.modeltvector3f;
9274         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9275         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9276         rsurface.normal3f  = rsurface.modelnormal3f;
9277         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9278         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9279         // if vertices are deformed (sprite flares and things in maps, possibly
9280         // water waves, bulges and other deformations), generate them into
9281         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9282         // (may be static model data or generated data for an animated model, or
9283         //  the previous deform pass)
9284         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9285         {
9286                 switch (deform->deform)
9287                 {
9288                 default:
9289                 case Q3DEFORM_PROJECTIONSHADOW:
9290                 case Q3DEFORM_TEXT0:
9291                 case Q3DEFORM_TEXT1:
9292                 case Q3DEFORM_TEXT2:
9293                 case Q3DEFORM_TEXT3:
9294                 case Q3DEFORM_TEXT4:
9295                 case Q3DEFORM_TEXT5:
9296                 case Q3DEFORM_TEXT6:
9297                 case Q3DEFORM_TEXT7:
9298                 case Q3DEFORM_NONE:
9299                         break;
9300                 case Q3DEFORM_AUTOSPRITE:
9301                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9302                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9303                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9304                         VectorNormalize(newforward);
9305                         VectorNormalize(newright);
9306                         VectorNormalize(newup);
9307                         // make deformed versions of only the model vertices used by the specified surfaces
9308                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9309                         {
9310                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9311                                 // a single autosprite surface can contain multiple sprites...
9312                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9313                                 {
9314                                         VectorClear(center);
9315                                         for (i = 0;i < 4;i++)
9316                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9317                                         VectorScale(center, 0.25f, center);
9318                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9319                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9320                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9321                                         for (i = 0;i < 4;i++)
9322                                         {
9323                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9324                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9325                                         }
9326                                 }
9327                                 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);
9328                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
9329                         }
9330                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9331                         rsurface.vertex3f_bufferobject = 0;
9332                         rsurface.vertex3f_bufferoffset = 0;
9333                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9334                         rsurface.svector3f_bufferobject = 0;
9335                         rsurface.svector3f_bufferoffset = 0;
9336                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9337                         rsurface.tvector3f_bufferobject = 0;
9338                         rsurface.tvector3f_bufferoffset = 0;
9339                         rsurface.normal3f = rsurface.array_deformednormal3f;
9340                         rsurface.normal3f_bufferobject = 0;
9341                         rsurface.normal3f_bufferoffset = 0;
9342                         break;
9343                 case Q3DEFORM_AUTOSPRITE2:
9344                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9345                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9346                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9347                         VectorNormalize(newforward);
9348                         VectorNormalize(newright);
9349                         VectorNormalize(newup);
9350                         // make deformed versions of only the model vertices used by the specified surfaces
9351                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9352                         {
9353                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9354                                 const float *v1, *v2;
9355                                 vec3_t start, end;
9356                                 float f, l;
9357                                 struct
9358                                 {
9359                                         float length2;
9360                                         const float *v1;
9361                                         const float *v2;
9362                                 }
9363                                 shortest[2];
9364                                 memset(shortest, 0, sizeof(shortest));
9365                                 // a single autosprite surface can contain multiple sprites...
9366                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9367                                 {
9368                                         VectorClear(center);
9369                                         for (i = 0;i < 4;i++)
9370                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9371                                         VectorScale(center, 0.25f, center);
9372                                         // find the two shortest edges, then use them to define the
9373                                         // axis vectors for rotating around the central axis
9374                                         for (i = 0;i < 6;i++)
9375                                         {
9376                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9377                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9378 #if 0
9379                                                 Debug_PolygonBegin(NULL, 0);
9380                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9381                                                 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);
9382                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9383                                                 Debug_PolygonEnd();
9384 #endif
9385                                                 l = VectorDistance2(v1, v2);
9386                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9387                                                 if (v1[2] != v2[2])
9388                                                         l += (1.0f / 1024.0f);
9389                                                 if (shortest[0].length2 > l || i == 0)
9390                                                 {
9391                                                         shortest[1] = shortest[0];
9392                                                         shortest[0].length2 = l;
9393                                                         shortest[0].v1 = v1;
9394                                                         shortest[0].v2 = v2;
9395                                                 }
9396                                                 else if (shortest[1].length2 > l || i == 1)
9397                                                 {
9398                                                         shortest[1].length2 = l;
9399                                                         shortest[1].v1 = v1;
9400                                                         shortest[1].v2 = v2;
9401                                                 }
9402                                         }
9403                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9404                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9405 #if 0
9406                                         Debug_PolygonBegin(NULL, 0);
9407                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9408                                         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);
9409                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9410                                         Debug_PolygonEnd();
9411 #endif
9412                                         // this calculates the right vector from the shortest edge
9413                                         // and the up vector from the edge midpoints
9414                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9415                                         VectorNormalize(right);
9416                                         VectorSubtract(end, start, up);
9417                                         VectorNormalize(up);
9418                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9419                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9420                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9421                                         VectorNegate(forward, forward);
9422                                         VectorReflect(forward, 0, up, forward);
9423                                         VectorNormalize(forward);
9424                                         CrossProduct(up, forward, newright);
9425                                         VectorNormalize(newright);
9426 #if 0
9427                                         Debug_PolygonBegin(NULL, 0);
9428                                         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);
9429                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9430                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9431                                         Debug_PolygonEnd();
9432 #endif
9433 #if 0
9434                                         Debug_PolygonBegin(NULL, 0);
9435                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9436                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9437                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9438                                         Debug_PolygonEnd();
9439 #endif
9440                                         // rotate the quad around the up axis vector, this is made
9441                                         // especially easy by the fact we know the quad is flat,
9442                                         // so we only have to subtract the center position and
9443                                         // measure distance along the right vector, and then
9444                                         // multiply that by the newright vector and add back the
9445                                         // center position
9446                                         // we also need to subtract the old position to undo the
9447                                         // displacement from the center, which we do with a
9448                                         // DotProduct, the subtraction/addition of center is also
9449                                         // optimized into DotProducts here
9450                                         l = DotProduct(right, center);
9451                                         for (i = 0;i < 4;i++)
9452                                         {
9453                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9454                                                 f = DotProduct(right, v1) - l;
9455                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9456                                         }
9457                                 }
9458                                 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);
9459                                 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);
9460                         }
9461                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9462                         rsurface.vertex3f_bufferobject = 0;
9463                         rsurface.vertex3f_bufferoffset = 0;
9464                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9465                         rsurface.svector3f_bufferobject = 0;
9466                         rsurface.svector3f_bufferoffset = 0;
9467                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9468                         rsurface.tvector3f_bufferobject = 0;
9469                         rsurface.tvector3f_bufferoffset = 0;
9470                         rsurface.normal3f = rsurface.array_deformednormal3f;
9471                         rsurface.normal3f_bufferobject = 0;
9472                         rsurface.normal3f_bufferoffset = 0;
9473                         break;
9474                 case Q3DEFORM_NORMAL:
9475                         // deform the normals to make reflections wavey
9476                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9477                         {
9478                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9479                                 for (j = 0;j < surface->num_vertices;j++)
9480                                 {
9481                                         float vertex[3];
9482                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9483                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9484                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9485                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9486                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9487                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9488                                         VectorNormalize(normal);
9489                                 }
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.svector3f = rsurface.array_deformedsvector3f;
9493                         rsurface.svector3f_bufferobject = 0;
9494                         rsurface.svector3f_bufferoffset = 0;
9495                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9496                         rsurface.tvector3f_bufferobject = 0;
9497                         rsurface.tvector3f_bufferoffset = 0;
9498                         rsurface.normal3f = rsurface.array_deformednormal3f;
9499                         rsurface.normal3f_bufferobject = 0;
9500                         rsurface.normal3f_bufferoffset = 0;
9501                         break;
9502                 case Q3DEFORM_WAVE:
9503                         // deform vertex array to make wavey water and flags and such
9504                         waveparms[0] = deform->waveparms[0];
9505                         waveparms[1] = deform->waveparms[1];
9506                         waveparms[2] = deform->waveparms[2];
9507                         waveparms[3] = deform->waveparms[3];
9508                         // this is how a divisor of vertex influence on deformation
9509                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9510                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9511                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9512                         {
9513                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9514                                 for (j = 0;j < surface->num_vertices;j++)
9515                                 {
9516                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9517                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9518                                         // if the wavefunc depends on time, evaluate it per-vertex
9519                                         if (waveparms[3])
9520                                         {
9521                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9522                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9523                                         }
9524                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9525                                 }
9526                         }
9527                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9528                         rsurface.vertex3f_bufferobject = 0;
9529                         rsurface.vertex3f_bufferoffset = 0;
9530                         break;
9531                 case Q3DEFORM_BULGE:
9532                         // deform vertex array to make the surface have moving bulges
9533                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9534                         {
9535                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9536                                 for (j = 0;j < surface->num_vertices;j++)
9537                                 {
9538                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9539                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9540                                 }
9541                         }
9542                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9543                         rsurface.vertex3f_bufferobject = 0;
9544                         rsurface.vertex3f_bufferoffset = 0;
9545                         break;
9546                 case Q3DEFORM_MOVE:
9547                         // deform vertex array
9548                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9549                         VectorScale(deform->parms, scale, waveparms);
9550                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9551                         {
9552                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9553                                 for (j = 0;j < surface->num_vertices;j++)
9554                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9555                         }
9556                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9557                         rsurface.vertex3f_bufferobject = 0;
9558                         rsurface.vertex3f_bufferoffset = 0;
9559                         break;
9560                 }
9561         }
9562         // generate texcoords based on the chosen texcoord source
9563         switch(rsurface.texture->tcgen.tcgen)
9564         {
9565         default:
9566         case Q3TCGEN_TEXTURE:
9567                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9568                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9569                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9570                 break;
9571         case Q3TCGEN_LIGHTMAP:
9572                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9573                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9574                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9575                 break;
9576         case Q3TCGEN_VECTOR:
9577                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9578                 {
9579                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9580                         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)
9581                         {
9582                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9583                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9584                         }
9585                 }
9586                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9587                 rsurface.texcoordtexture2f_bufferobject  = 0;
9588                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9589                 break;
9590         case Q3TCGEN_ENVIRONMENT:
9591                 // make environment reflections using a spheremap
9592                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9593                 {
9594                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9595                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9596                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9597                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9598                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9599                         {
9600                                 // identical to Q3A's method, but executed in worldspace so
9601                                 // carried models can be shiny too
9602
9603                                 float viewer[3], d, reflected[3], worldreflected[3];
9604
9605                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9606                                 // VectorNormalize(viewer);
9607
9608                                 d = DotProduct(normal, viewer);
9609
9610                                 reflected[0] = normal[0]*2*d - viewer[0];
9611                                 reflected[1] = normal[1]*2*d - viewer[1];
9612                                 reflected[2] = normal[2]*2*d - viewer[2];
9613                                 // note: this is proportinal to viewer, so we can normalize later
9614
9615                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9616                                 VectorNormalize(worldreflected);
9617
9618                                 // note: this sphere map only uses world x and z!
9619                                 // so positive and negative y will LOOK THE SAME.
9620                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9621                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9622                         }
9623                 }
9624                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9625                 rsurface.texcoordtexture2f_bufferobject  = 0;
9626                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9627                 break;
9628         }
9629         // the only tcmod that needs software vertex processing is turbulent, so
9630         // check for it here and apply the changes if needed
9631         // and we only support that as the first one
9632         // (handling a mixture of turbulent and other tcmods would be problematic
9633         //  without punting it entirely to a software path)
9634         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9635         {
9636                 amplitude = rsurface.texture->tcmods[0].parms[1];
9637                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9638                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9639                 {
9640                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9641                         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)
9642                         {
9643                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9644                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9645                         }
9646                 }
9647                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9648                 rsurface.texcoordtexture2f_bufferobject  = 0;
9649                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9650         }
9651         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9652         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9653         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9654         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9655 }
9656
9657 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9658 {
9659         int i, j;
9660         const msurface_t *surface = texturesurfacelist[0];
9661         const msurface_t *surface2;
9662         int firstvertex;
9663         int endvertex;
9664         int numvertices;
9665         int numtriangles;
9666         // TODO: lock all array ranges before render, rather than on each surface
9667         if (texturenumsurfaces == 1)
9668         {
9669                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9670                 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);
9671         }
9672         else if (r_batchmode.integer == 2)
9673         {
9674                 #define MAXBATCHTRIANGLES 4096
9675                 int batchtriangles = 0;
9676                 static int batchelements[MAXBATCHTRIANGLES*3];
9677                 for (i = 0;i < texturenumsurfaces;i = j)
9678                 {
9679                         surface = texturesurfacelist[i];
9680                         j = i + 1;
9681                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9682                         {
9683                                 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);
9684                                 continue;
9685                         }
9686                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9687                         batchtriangles = surface->num_triangles;
9688                         firstvertex = surface->num_firstvertex;
9689                         endvertex = surface->num_firstvertex + surface->num_vertices;
9690                         for (;j < texturenumsurfaces;j++)
9691                         {
9692                                 surface2 = texturesurfacelist[j];
9693                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9694                                         break;
9695                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9696                                 batchtriangles += surface2->num_triangles;
9697                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9698                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9699                         }
9700                         surface2 = texturesurfacelist[j-1];
9701                         numvertices = endvertex - firstvertex;
9702                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9703                 }
9704         }
9705         else if (r_batchmode.integer == 1)
9706         {
9707                 for (i = 0;i < texturenumsurfaces;i = j)
9708                 {
9709                         surface = texturesurfacelist[i];
9710                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9711                                 if (texturesurfacelist[j] != surface2)
9712                                         break;
9713                         surface2 = texturesurfacelist[j-1];
9714                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9715                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9716                         GL_LockArrays(surface->num_firstvertex, numvertices);
9717                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9718                 }
9719         }
9720         else
9721         {
9722                 for (i = 0;i < texturenumsurfaces;i++)
9723                 {
9724                         surface = texturesurfacelist[i];
9725                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9726                         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);
9727                 }
9728         }
9729 }
9730
9731 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9732 {
9733         switch(vid.renderpath)
9734         {
9735         case RENDERPATH_CGGL:
9736 #ifdef SUPPORTCG
9737                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9738                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9739 #endif
9740                 break;
9741         case RENDERPATH_GL20:
9742                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9743                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9744                 break;
9745         case RENDERPATH_GL13:
9746         case RENDERPATH_GL11:
9747                 R_Mesh_TexBind(0, surface->lightmaptexture);
9748                 break;
9749         }
9750 }
9751
9752 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9753 {
9754         // pick the closest matching water plane and bind textures
9755         int planeindex, vertexindex;
9756         float d, bestd;
9757         vec3_t vert;
9758         const float *v;
9759         r_waterstate_waterplane_t *p, *bestp;
9760         bestd = 0;
9761         bestp = NULL;
9762         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9763         {
9764                 d = 0;
9765                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9766                 {
9767                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9768                         d += fabs(PlaneDiff(vert, &p->plane));
9769                 }
9770                 if (bestd > d || !bestp)
9771                 {
9772                         bestd = d;
9773                         bestp = p;
9774                 }
9775         }
9776         switch(vid.renderpath)
9777         {
9778         case RENDERPATH_CGGL:
9779 #ifdef SUPPORTCG
9780                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9781                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9782 #endif
9783                 break;
9784         case RENDERPATH_GL20:
9785                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9786                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9787                 break;
9788         case RENDERPATH_GL13:
9789         case RENDERPATH_GL11:
9790                 break;
9791         }
9792 }
9793
9794 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9795 {
9796         int i;
9797         const msurface_t *surface;
9798         if (r_waterstate.renderingscene)
9799                 return;
9800         for (i = 0;i < texturenumsurfaces;i++)
9801         {
9802                 surface = texturesurfacelist[i];
9803                 RSurf_BindLightmapForSurface(surface);
9804                 RSurf_BindReflectionForSurface(surface);
9805                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9806                 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);
9807         }
9808 }
9809
9810 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9811 {
9812         int i;
9813         int j;
9814         const msurface_t *surface = texturesurfacelist[0];
9815         const msurface_t *surface2;
9816         int firstvertex;
9817         int endvertex;
9818         int numvertices;
9819         int numtriangles;
9820         if (texturenumsurfaces == 1)
9821         {
9822                 RSurf_BindLightmapForSurface(surface);
9823                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9824                 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);
9825         }
9826         else if (r_batchmode.integer == 2)
9827         {
9828 #define MAXBATCHTRIANGLES 4096
9829                 int batchtriangles = 0;
9830                 static int batchelements[MAXBATCHTRIANGLES*3];
9831                 for (i = 0;i < texturenumsurfaces;i = j)
9832                 {
9833                         surface = texturesurfacelist[i];
9834                         RSurf_BindLightmapForSurface(surface);
9835                         j = i + 1;
9836                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9837                         {
9838                                 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);
9839                                 continue;
9840                         }
9841                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9842                         batchtriangles = surface->num_triangles;
9843                         firstvertex = surface->num_firstvertex;
9844                         endvertex = surface->num_firstvertex + surface->num_vertices;
9845                         for (;j < texturenumsurfaces;j++)
9846                         {
9847                                 surface2 = texturesurfacelist[j];
9848                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9849                                         break;
9850                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9851                                 batchtriangles += surface2->num_triangles;
9852                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9853                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9854                         }
9855                         surface2 = texturesurfacelist[j-1];
9856                         numvertices = endvertex - firstvertex;
9857                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9858                 }
9859         }
9860         else if (r_batchmode.integer == 1)
9861         {
9862 #if 0
9863                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9864                 for (i = 0;i < texturenumsurfaces;i = j)
9865                 {
9866                         surface = texturesurfacelist[i];
9867                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9868                                 if (texturesurfacelist[j] != surface2)
9869                                         break;
9870                         Con_Printf(" %i", j - i);
9871                 }
9872                 Con_Printf("\n");
9873                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9874 #endif
9875                 for (i = 0;i < texturenumsurfaces;i = j)
9876                 {
9877                         surface = texturesurfacelist[i];
9878                         RSurf_BindLightmapForSurface(surface);
9879                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9880                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9881                                         break;
9882 #if 0
9883                         Con_Printf(" %i", j - i);
9884 #endif
9885                         surface2 = texturesurfacelist[j-1];
9886                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9887                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9888                         GL_LockArrays(surface->num_firstvertex, numvertices);
9889                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9890                 }
9891 #if 0
9892                 Con_Printf("\n");
9893 #endif
9894         }
9895         else
9896         {
9897                 for (i = 0;i < texturenumsurfaces;i++)
9898                 {
9899                         surface = texturesurfacelist[i];
9900                         RSurf_BindLightmapForSurface(surface);
9901                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9902                         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);
9903                 }
9904         }
9905 }
9906
9907 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9908 {
9909         int j;
9910         int texturesurfaceindex;
9911         if (r_showsurfaces.integer == 2)
9912         {
9913                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9914                 {
9915                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9916                         for (j = 0;j < surface->num_triangles;j++)
9917                         {
9918                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9919                                 GL_Color(f, f, f, 1);
9920                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9921                         }
9922                 }
9923         }
9924         else
9925         {
9926                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9927                 {
9928                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9929                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9930                         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);
9931                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9932                         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);
9933                 }
9934         }
9935 }
9936
9937 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9938 {
9939         int texturesurfaceindex;
9940         int i;
9941         const float *v;
9942         float *c2;
9943         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9944         {
9945                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9946                 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)
9947                 {
9948                         c2[0] = 0.5;
9949                         c2[1] = 0.5;
9950                         c2[2] = 0.5;
9951                         c2[3] = 1;
9952                 }
9953         }
9954         rsurface.lightmapcolor4f = rsurface.array_color4f;
9955         rsurface.lightmapcolor4f_bufferobject = 0;
9956         rsurface.lightmapcolor4f_bufferoffset = 0;
9957 }
9958
9959 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9960 {
9961         int texturesurfaceindex;
9962         int i;
9963         float f;
9964         const float *v;
9965         const float *c;
9966         float *c2;
9967         if (rsurface.lightmapcolor4f)
9968         {
9969                 // generate color arrays for the surfaces in this list
9970                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9971                 {
9972                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9973                         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)
9974                         {
9975                                 f = RSurf_FogVertex(v);
9976                                 c2[0] = c[0] * f;
9977                                 c2[1] = c[1] * f;
9978                                 c2[2] = c[2] * f;
9979                                 c2[3] = c[3];
9980                         }
9981                 }
9982         }
9983         else
9984         {
9985                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9986                 {
9987                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9988                         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)
9989                         {
9990                                 f = RSurf_FogVertex(v);
9991                                 c2[0] = f;
9992                                 c2[1] = f;
9993                                 c2[2] = f;
9994                                 c2[3] = 1;
9995                         }
9996                 }
9997         }
9998         rsurface.lightmapcolor4f = rsurface.array_color4f;
9999         rsurface.lightmapcolor4f_bufferobject = 0;
10000         rsurface.lightmapcolor4f_bufferoffset = 0;
10001 }
10002
10003 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10004 {
10005         int texturesurfaceindex;
10006         int i;
10007         float f;
10008         const float *v;
10009         const float *c;
10010         float *c2;
10011         if (!rsurface.lightmapcolor4f)
10012                 return;
10013         // generate color arrays for the surfaces in this list
10014         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10015         {
10016                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10017                 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)
10018                 {
10019                         f = RSurf_FogVertex(v);
10020                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10021                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10022                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10023                         c2[3] = c[3];
10024                 }
10025         }
10026         rsurface.lightmapcolor4f = rsurface.array_color4f;
10027         rsurface.lightmapcolor4f_bufferobject = 0;
10028         rsurface.lightmapcolor4f_bufferoffset = 0;
10029 }
10030
10031 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10032 {
10033         int texturesurfaceindex;
10034         int i;
10035         const float *c;
10036         float *c2;
10037         if (!rsurface.lightmapcolor4f)
10038                 return;
10039         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10040         {
10041                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10042                 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)
10043                 {
10044                         c2[0] = c[0] * r;
10045                         c2[1] = c[1] * g;
10046                         c2[2] = c[2] * b;
10047                         c2[3] = c[3] * a;
10048                 }
10049         }
10050         rsurface.lightmapcolor4f = rsurface.array_color4f;
10051         rsurface.lightmapcolor4f_bufferobject = 0;
10052         rsurface.lightmapcolor4f_bufferoffset = 0;
10053 }
10054
10055 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10056 {
10057         int texturesurfaceindex;
10058         int i;
10059         const float *c;
10060         float *c2;
10061         if (!rsurface.lightmapcolor4f)
10062                 return;
10063         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10064         {
10065                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10066                 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)
10067                 {
10068                         c2[0] = c[0] + r_refdef.scene.ambient;
10069                         c2[1] = c[1] + r_refdef.scene.ambient;
10070                         c2[2] = c[2] + r_refdef.scene.ambient;
10071                         c2[3] = c[3];
10072                 }
10073         }
10074         rsurface.lightmapcolor4f = rsurface.array_color4f;
10075         rsurface.lightmapcolor4f_bufferobject = 0;
10076         rsurface.lightmapcolor4f_bufferoffset = 0;
10077 }
10078
10079 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10080 {
10081         // TODO: optimize
10082         rsurface.lightmapcolor4f = NULL;
10083         rsurface.lightmapcolor4f_bufferobject = 0;
10084         rsurface.lightmapcolor4f_bufferoffset = 0;
10085         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10086         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10087         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10088         GL_Color(r, g, b, a);
10089         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10090 }
10091
10092 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10093 {
10094         // TODO: optimize applyfog && applycolor case
10095         // just apply fog if necessary, and tint the fog color array if necessary
10096         rsurface.lightmapcolor4f = NULL;
10097         rsurface.lightmapcolor4f_bufferobject = 0;
10098         rsurface.lightmapcolor4f_bufferoffset = 0;
10099         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10100         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10101         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10102         GL_Color(r, g, b, a);
10103         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10104 }
10105
10106 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10107 {
10108         int texturesurfaceindex;
10109         int i;
10110         float *c;
10111         // TODO: optimize
10112         if (texturesurfacelist[0]->lightmapinfo)
10113         {
10114                 // generate color arrays for the surfaces in this list
10115                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10116                 {
10117                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10118                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10119                         {
10120                                 if (surface->lightmapinfo->samples)
10121                                 {
10122                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10123                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10124                                         VectorScale(lm, scale, c);
10125                                         if (surface->lightmapinfo->styles[1] != 255)
10126                                         {
10127                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10128                                                 lm += size3;
10129                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10130                                                 VectorMA(c, scale, lm, c);
10131                                                 if (surface->lightmapinfo->styles[2] != 255)
10132                                                 {
10133                                                         lm += size3;
10134                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10135                                                         VectorMA(c, scale, lm, c);
10136                                                         if (surface->lightmapinfo->styles[3] != 255)
10137                                                         {
10138                                                                 lm += size3;
10139                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10140                                                                 VectorMA(c, scale, lm, c);
10141                                                         }
10142                                                 }
10143                                         }
10144                                 }
10145                                 else
10146                                         VectorClear(c);
10147                                 c[3] = 1;
10148                         }
10149                 }
10150                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10151                 rsurface.lightmapcolor4f_bufferobject = 0;
10152                 rsurface.lightmapcolor4f_bufferoffset = 0;
10153         }
10154         else
10155         {
10156                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10157                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10158                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10159         }
10160         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10161         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10162         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10163         GL_Color(r, g, b, a);
10164         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10165 }
10166
10167 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10168 {
10169         int texturesurfaceindex;
10170         int i;
10171         float f;
10172         float alpha;
10173         const float *v;
10174         const float *n;
10175         float *c;
10176         vec3_t ambientcolor;
10177         vec3_t diffusecolor;
10178         vec3_t lightdir;
10179         // TODO: optimize
10180         // model lighting
10181         VectorCopy(rsurface.modellight_lightdir, lightdir);
10182         f = 0.5f * r_refdef.lightmapintensity;
10183         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10184         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10185         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10186         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10187         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10188         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10189         alpha = *a;
10190         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10191         {
10192                 // generate color arrays for the surfaces in this list
10193                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10194                 {
10195                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10196                         int numverts = surface->num_vertices;
10197                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10198                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10199                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10200                         // q3-style directional shading
10201                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10202                         {
10203                                 if ((f = DotProduct(n, lightdir)) > 0)
10204                                         VectorMA(ambientcolor, f, diffusecolor, c);
10205                                 else
10206                                         VectorCopy(ambientcolor, c);
10207                                 c[3] = alpha;
10208                         }
10209                 }
10210                 *r = 1;
10211                 *g = 1;
10212                 *b = 1;
10213                 *a = 1;
10214                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10215                 rsurface.lightmapcolor4f_bufferobject = 0;
10216                 rsurface.lightmapcolor4f_bufferoffset = 0;
10217                 *applycolor = false;
10218         }
10219         else
10220         {
10221                 *r = ambientcolor[0];
10222                 *g = ambientcolor[1];
10223                 *b = ambientcolor[2];
10224                 rsurface.lightmapcolor4f = NULL;
10225                 rsurface.lightmapcolor4f_bufferobject = 0;
10226                 rsurface.lightmapcolor4f_bufferoffset = 0;
10227         }
10228 }
10229
10230 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10231 {
10232         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10233         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10234         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10235         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10236         GL_Color(r, g, b, a);
10237         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10238 }
10239
10240 void RSurf_SetupDepthAndCulling(void)
10241 {
10242         // submodels are biased to avoid z-fighting with world surfaces that they
10243         // may be exactly overlapping (avoids z-fighting artifacts on certain
10244         // doors and things in Quake maps)
10245         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10246         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10247         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10248         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10249 }
10250
10251 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10252 {
10253         // transparent sky would be ridiculous
10254         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10255                 return;
10256         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10257         skyrenderlater = true;
10258         RSurf_SetupDepthAndCulling();
10259         GL_DepthMask(true);
10260         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10261         // skymasking on them, and Quake3 never did sky masking (unlike
10262         // software Quake and software Quake2), so disable the sky masking
10263         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10264         // and skymasking also looks very bad when noclipping outside the
10265         // level, so don't use it then either.
10266         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10267         {
10268                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10269                 R_Mesh_ColorPointer(NULL, 0, 0);
10270                 R_Mesh_ResetTextureState();
10271                 if (skyrendermasked)
10272                 {
10273                         R_SetupShader_DepthOrShadow();
10274                         // depth-only (masking)
10275                         GL_ColorMask(0,0,0,0);
10276                         // just to make sure that braindead drivers don't draw
10277                         // anything despite that colormask...
10278                         GL_BlendFunc(GL_ZERO, GL_ONE);
10279                 }
10280                 else
10281                 {
10282                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10283                         // fog sky
10284                         GL_BlendFunc(GL_ONE, GL_ZERO);
10285                 }
10286                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10287                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10288                 if (skyrendermasked)
10289                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10290         }
10291         R_Mesh_ResetTextureState();
10292         GL_Color(1, 1, 1, 1);
10293 }
10294
10295 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10296 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10297 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10298 {
10299         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10300         if (prepass)
10301         {
10302                 // render screenspace normalmap to texture
10303                 GL_DepthMask(true);
10304                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10305                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10306                 GL_LockArrays(0, 0);
10307         }
10308         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10309         {
10310                 // render water or distortion background, then blend surface on top
10311                 GL_DepthMask(true);
10312                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10313                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10314                 GL_LockArrays(0, 0);
10315                 GL_DepthMask(false);
10316                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10317                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10318                 GL_LockArrays(0, 0);
10319         }
10320         else
10321         {
10322                 // render surface normally
10323                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10324                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10325                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10326                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10327                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10328                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10329                 else
10330                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10331                 GL_LockArrays(0, 0);
10332         }
10333 }
10334
10335 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10336 {
10337         // OpenGL 1.3 path - anything not completely ancient
10338         int texturesurfaceindex;
10339         qboolean applycolor;
10340         qboolean applyfog;
10341         int layerindex;
10342         const texturelayer_t *layer;
10343         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10344
10345         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10346         {
10347                 vec4_t layercolor;
10348                 int layertexrgbscale;
10349                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10350                 {
10351                         if (layerindex == 0)
10352                                 GL_AlphaTest(true);
10353                         else
10354                         {
10355                                 GL_AlphaTest(false);
10356                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10357                         }
10358                 }
10359                 GL_DepthMask(layer->depthmask && writedepth);
10360                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10361                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10362                 {
10363                         layertexrgbscale = 4;
10364                         VectorScale(layer->color, 0.25f, layercolor);
10365                 }
10366                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10367                 {
10368                         layertexrgbscale = 2;
10369                         VectorScale(layer->color, 0.5f, layercolor);
10370                 }
10371                 else
10372                 {
10373                         layertexrgbscale = 1;
10374                         VectorScale(layer->color, 1.0f, layercolor);
10375                 }
10376                 layercolor[3] = layer->color[3];
10377                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10378                 R_Mesh_ColorPointer(NULL, 0, 0);
10379                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10380                 switch (layer->type)
10381                 {
10382                 case TEXTURELAYERTYPE_LITTEXTURE:
10383                         // single-pass lightmapped texture with 2x rgbscale
10384                         //R_Mesh_TexBind(0, r_texture_white);
10385                         R_Mesh_TexMatrix(0, NULL);
10386                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10387                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10388                         R_Mesh_TexBind(1, layer->texture);
10389                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10390                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10391                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10392                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10393                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10394                         else if (rsurface.uselightmaptexture)
10395                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10396                         else
10397                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10398                         break;
10399                 case TEXTURELAYERTYPE_TEXTURE:
10400                         // singletexture unlit texture with transparency support
10401                         R_Mesh_TexBind(0, layer->texture);
10402                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10403                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10404                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10405                         R_Mesh_TexBind(1, 0);
10406                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10407                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10408                         break;
10409                 case TEXTURELAYERTYPE_FOG:
10410                         // singletexture fogging
10411                         if (layer->texture)
10412                         {
10413                                 R_Mesh_TexBind(0, layer->texture);
10414                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10415                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10416                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10417                         }
10418                         else
10419                         {
10420                                 R_Mesh_TexBind(0, 0);
10421                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10422                         }
10423                         R_Mesh_TexBind(1, 0);
10424                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10425                         // generate a color array for the fog pass
10426                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10427                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10428                         {
10429                                 int i;
10430                                 float f;
10431                                 const float *v;
10432                                 float *c;
10433                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10434                                 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)
10435                                 {
10436                                         f = 1 - RSurf_FogVertex(v);
10437                                         c[0] = layercolor[0];
10438                                         c[1] = layercolor[1];
10439                                         c[2] = layercolor[2];
10440                                         c[3] = f * layercolor[3];
10441                                 }
10442                         }
10443                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10444                         break;
10445                 default:
10446                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10447                 }
10448                 GL_LockArrays(0, 0);
10449         }
10450         CHECKGLERROR
10451         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10452         {
10453                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10454                 GL_AlphaTest(false);
10455         }
10456 }
10457
10458 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10459 {
10460         // OpenGL 1.1 - crusty old voodoo path
10461         int texturesurfaceindex;
10462         qboolean applyfog;
10463         int layerindex;
10464         const texturelayer_t *layer;
10465         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10466
10467         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10468         {
10469                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10470                 {
10471                         if (layerindex == 0)
10472                                 GL_AlphaTest(true);
10473                         else
10474                         {
10475                                 GL_AlphaTest(false);
10476                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10477                         }
10478                 }
10479                 GL_DepthMask(layer->depthmask && writedepth);
10480                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10481                 R_Mesh_ColorPointer(NULL, 0, 0);
10482                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10483                 switch (layer->type)
10484                 {
10485                 case TEXTURELAYERTYPE_LITTEXTURE:
10486                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10487                         {
10488                                 // two-pass lit texture with 2x rgbscale
10489                                 // first the lightmap pass
10490                                 //R_Mesh_TexBind(0, r_texture_white);
10491                                 R_Mesh_TexMatrix(0, NULL);
10492                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10493                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10494                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10495                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10496                                 else if (rsurface.uselightmaptexture)
10497                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10498                                 else
10499                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10500                                 GL_LockArrays(0, 0);
10501                                 // then apply the texture to it
10502                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10503                                 R_Mesh_TexBind(0, layer->texture);
10504                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10505                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10506                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10507                                 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);
10508                         }
10509                         else
10510                         {
10511                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10512                                 R_Mesh_TexBind(0, layer->texture);
10513                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10514                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10515                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10516                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10517                                         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);
10518                                 else
10519                                         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);
10520                         }
10521                         break;
10522                 case TEXTURELAYERTYPE_TEXTURE:
10523                         // singletexture unlit texture with transparency support
10524                         R_Mesh_TexBind(0, layer->texture);
10525                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10526                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10527                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10528                         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);
10529                         break;
10530                 case TEXTURELAYERTYPE_FOG:
10531                         // singletexture fogging
10532                         if (layer->texture)
10533                         {
10534                                 R_Mesh_TexBind(0, layer->texture);
10535                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10536                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10537                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10538                         }
10539                         else
10540                         {
10541                                 R_Mesh_TexBind(0, 0);
10542                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10543                         }
10544                         // generate a color array for the fog pass
10545                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10546                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10547                         {
10548                                 int i;
10549                                 float f;
10550                                 const float *v;
10551                                 float *c;
10552                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10553                                 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)
10554                                 {
10555                                         f = 1 - RSurf_FogVertex(v);
10556                                         c[0] = layer->color[0];
10557                                         c[1] = layer->color[1];
10558                                         c[2] = layer->color[2];
10559                                         c[3] = f * layer->color[3];
10560                                 }
10561                         }
10562                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10563                         break;
10564                 default:
10565                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10566                 }
10567                 GL_LockArrays(0, 0);
10568         }
10569         CHECKGLERROR
10570         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10571         {
10572                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10573                 GL_AlphaTest(false);
10574         }
10575 }
10576
10577 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10578 {
10579         float c[4];
10580
10581         GL_AlphaTest(false);
10582         R_Mesh_ColorPointer(NULL, 0, 0);
10583         R_Mesh_ResetTextureState();
10584         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10585
10586         if(rsurface.texture && rsurface.texture->currentskinframe)
10587         {
10588                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10589                 c[3] *= rsurface.texture->currentalpha;
10590         }
10591         else
10592         {
10593                 c[0] = 1;
10594                 c[1] = 0;
10595                 c[2] = 1;
10596                 c[3] = 1;
10597         }
10598
10599         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10600         {
10601                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10602                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10603                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10604         }
10605
10606         // brighten it up (as texture value 127 means "unlit")
10607         c[0] *= 2 * r_refdef.view.colorscale;
10608         c[1] *= 2 * r_refdef.view.colorscale;
10609         c[2] *= 2 * r_refdef.view.colorscale;
10610
10611         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10612                 c[3] *= r_wateralpha.value;
10613
10614         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10615         {
10616                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10617                 GL_DepthMask(false);
10618         }
10619         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10620         {
10621                 GL_BlendFunc(GL_ONE, GL_ONE);
10622                 GL_DepthMask(false);
10623         }
10624         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10625         {
10626                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10627                 GL_DepthMask(false);
10628         }
10629         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10630         {
10631                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10632                 GL_DepthMask(false);
10633         }
10634         else
10635         {
10636                 GL_BlendFunc(GL_ONE, GL_ZERO);
10637                 GL_DepthMask(writedepth);
10638         }
10639
10640         rsurface.lightmapcolor4f = NULL;
10641
10642         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10643         {
10644                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10645
10646                 rsurface.lightmapcolor4f = NULL;
10647                 rsurface.lightmapcolor4f_bufferobject = 0;
10648                 rsurface.lightmapcolor4f_bufferoffset = 0;
10649         }
10650         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10651         {
10652                 qboolean applycolor = true;
10653                 float one = 1.0;
10654
10655                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10656
10657                 r_refdef.lightmapintensity = 1;
10658                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10659                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10660         }
10661         else
10662         {
10663                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10664
10665                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10666                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10667                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10668         }
10669
10670         if(!rsurface.lightmapcolor4f)
10671                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10672
10673         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10674         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10675         if(r_refdef.fogenabled)
10676                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10677
10678         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10679         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10680 }
10681
10682 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10683 {
10684         CHECKGLERROR
10685         RSurf_SetupDepthAndCulling();
10686         if (r_showsurfaces.integer == 3 && !prepass)
10687         {
10688                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10689                 return;
10690         }
10691         switch (vid.renderpath)
10692         {
10693         case RENDERPATH_GL20:
10694         case RENDERPATH_CGGL:
10695                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10696                 break;
10697         case RENDERPATH_GL13:
10698                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10699                 break;
10700         case RENDERPATH_GL11:
10701                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10702                 break;
10703         }
10704         CHECKGLERROR
10705 }
10706
10707 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10708 {
10709         CHECKGLERROR
10710         RSurf_SetupDepthAndCulling();
10711         if (r_showsurfaces.integer == 3 && !prepass)
10712         {
10713                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10714                 return;
10715         }
10716         switch (vid.renderpath)
10717         {
10718         case RENDERPATH_GL20:
10719         case RENDERPATH_CGGL:
10720                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10721                 break;
10722         case RENDERPATH_GL13:
10723                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10724                 break;
10725         case RENDERPATH_GL11:
10726                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10727                 break;
10728         }
10729         CHECKGLERROR
10730 }
10731
10732 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10733 {
10734         int i, j;
10735         int texturenumsurfaces, endsurface;
10736         texture_t *texture;
10737         const msurface_t *surface;
10738         const msurface_t *texturesurfacelist[256];
10739
10740         // if the model is static it doesn't matter what value we give for
10741         // wantnormals and wanttangents, so this logic uses only rules applicable
10742         // to a model, knowing that they are meaningless otherwise
10743         if (ent == r_refdef.scene.worldentity)
10744                 RSurf_ActiveWorldEntity();
10745         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10746                 RSurf_ActiveModelEntity(ent, false, false, false);
10747         else
10748         {
10749                 switch (vid.renderpath)
10750                 {
10751                 case RENDERPATH_GL20:
10752                 case RENDERPATH_CGGL:
10753                         RSurf_ActiveModelEntity(ent, true, true, false);
10754                         break;
10755                 case RENDERPATH_GL13:
10756                 case RENDERPATH_GL11:
10757                         RSurf_ActiveModelEntity(ent, true, false, false);
10758                         break;
10759                 }
10760         }
10761
10762         if (r_transparentdepthmasking.integer)
10763         {
10764                 qboolean setup = false;
10765                 for (i = 0;i < numsurfaces;i = j)
10766                 {
10767                         j = i + 1;
10768                         surface = rsurface.modelsurfaces + surfacelist[i];
10769                         texture = surface->texture;
10770                         rsurface.texture = R_GetCurrentTexture(texture);
10771                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10772                         // scan ahead until we find a different texture
10773                         endsurface = min(i + 1024, numsurfaces);
10774                         texturenumsurfaces = 0;
10775                         texturesurfacelist[texturenumsurfaces++] = surface;
10776                         for (;j < endsurface;j++)
10777                         {
10778                                 surface = rsurface.modelsurfaces + surfacelist[j];
10779                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10780                                         break;
10781                                 texturesurfacelist[texturenumsurfaces++] = surface;
10782                         }
10783                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10784                                 continue;
10785                         // render the range of surfaces as depth
10786                         if (!setup)
10787                         {
10788                                 setup = true;
10789                                 GL_ColorMask(0,0,0,0);
10790                                 GL_Color(1,1,1,1);
10791                                 GL_DepthTest(true);
10792                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10793                                 GL_DepthMask(true);
10794                                 GL_AlphaTest(false);
10795                                 R_Mesh_ColorPointer(NULL, 0, 0);
10796                                 R_Mesh_ResetTextureState();
10797                                 R_SetupShader_DepthOrShadow();
10798                         }
10799                         RSurf_SetupDepthAndCulling();
10800                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10801                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10802                 }
10803                 if (setup)
10804                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10805         }
10806
10807         for (i = 0;i < numsurfaces;i = j)
10808         {
10809                 j = i + 1;
10810                 surface = rsurface.modelsurfaces + surfacelist[i];
10811                 texture = surface->texture;
10812                 rsurface.texture = R_GetCurrentTexture(texture);
10813                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10814                 // scan ahead until we find a different texture
10815                 endsurface = min(i + 1024, numsurfaces);
10816                 texturenumsurfaces = 0;
10817                 texturesurfacelist[texturenumsurfaces++] = surface;
10818                 for (;j < endsurface;j++)
10819                 {
10820                         surface = rsurface.modelsurfaces + surfacelist[j];
10821                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10822                                 break;
10823                         texturesurfacelist[texturenumsurfaces++] = surface;
10824                 }
10825                 // render the range of surfaces
10826                 if (ent == r_refdef.scene.worldentity)
10827                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10828                 else
10829                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10830         }
10831         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10832         GL_AlphaTest(false);
10833 }
10834
10835 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10836 {
10837         // transparent surfaces get pushed off into the transparent queue
10838         int surfacelistindex;
10839         const msurface_t *surface;
10840         vec3_t tempcenter, center;
10841         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10842         {
10843                 surface = texturesurfacelist[surfacelistindex];
10844                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10845                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10846                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10847                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10848                 if (queueentity->transparent_offset) // transparent offset
10849                 {
10850                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10851                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10852                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10853                 }
10854                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10855         }
10856 }
10857
10858 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10859 {
10860         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10861         CHECKGLERROR
10862         if (depthonly)
10863         {
10864                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10865                         return;
10866                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10867                         return;
10868                 RSurf_SetupDepthAndCulling();
10869                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10870                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10871         }
10872         else if (prepass)
10873         {
10874                 if (!rsurface.texture->currentnumlayers)
10875                         return;
10876                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10877                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10878                 else
10879                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10880         }
10881         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10882         {
10883                 RSurf_SetupDepthAndCulling();
10884                 GL_AlphaTest(false);
10885                 R_Mesh_ColorPointer(NULL, 0, 0);
10886                 R_Mesh_ResetTextureState();
10887                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10888                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10889                 GL_DepthMask(true);
10890                 GL_BlendFunc(GL_ONE, GL_ZERO);
10891                 GL_Color(0, 0, 0, 1);
10892                 GL_DepthTest(writedepth);
10893                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10894         }
10895         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !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_DepthTest(true);
10906                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10907         }
10908         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10909                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10910         else if (!rsurface.texture->currentnumlayers)
10911                 return;
10912         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10913         {
10914                 // in the deferred case, transparent surfaces were queued during prepass
10915                 if (!r_shadow_usingdeferredprepass)
10916                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10917         }
10918         else
10919         {
10920                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10921                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10922         }
10923         CHECKGLERROR
10924 }
10925
10926 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10927 {
10928         int i, j;
10929         texture_t *texture;
10930         // break the surface list down into batches by texture and use of lightmapping
10931         for (i = 0;i < numsurfaces;i = j)
10932         {
10933                 j = i + 1;
10934                 // texture is the base texture pointer, rsurface.texture is the
10935                 // current frame/skin the texture is directing us to use (for example
10936                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10937                 // use skin 1 instead)
10938                 texture = surfacelist[i]->texture;
10939                 rsurface.texture = R_GetCurrentTexture(texture);
10940                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10941                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10942                 {
10943                         // if this texture is not the kind we want, skip ahead to the next one
10944                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10945                                 ;
10946                         continue;
10947                 }
10948                 // simply scan ahead until we find a different texture or lightmap state
10949                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10950                         ;
10951                 // render the range of surfaces
10952                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10953         }
10954 }
10955
10956 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10957 {
10958         CHECKGLERROR
10959         if (depthonly)
10960         {
10961                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10962                         return;
10963                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10964                         return;
10965                 RSurf_SetupDepthAndCulling();
10966                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10967                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10968         }
10969         else if (prepass)
10970         {
10971                 if (!rsurface.texture->currentnumlayers)
10972                         return;
10973                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10974                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10975                 else
10976                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10977         }
10978         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10979         {
10980                 RSurf_SetupDepthAndCulling();
10981                 GL_AlphaTest(false);
10982                 R_Mesh_ColorPointer(NULL, 0, 0);
10983                 R_Mesh_ResetTextureState();
10984                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10985                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10986                 GL_DepthMask(true);
10987                 GL_BlendFunc(GL_ONE, GL_ZERO);
10988                 GL_Color(0, 0, 0, 1);
10989                 GL_DepthTest(writedepth);
10990                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10991         }
10992         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
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_DepthTest(true);
11003                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11004         }
11005         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11006                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11007         else if (!rsurface.texture->currentnumlayers)
11008                 return;
11009         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11010         {
11011                 // in the deferred case, transparent surfaces were queued during prepass
11012                 if (!r_shadow_usingdeferredprepass)
11013                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11014         }
11015         else
11016         {
11017                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11018                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11019         }
11020         CHECKGLERROR
11021 }
11022
11023 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11024 {
11025         int i, j;
11026         texture_t *texture;
11027         // break the surface list down into batches by texture and use of lightmapping
11028         for (i = 0;i < numsurfaces;i = j)
11029         {
11030                 j = i + 1;
11031                 // texture is the base texture pointer, rsurface.texture is the
11032                 // current frame/skin the texture is directing us to use (for example
11033                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11034                 // use skin 1 instead)
11035                 texture = surfacelist[i]->texture;
11036                 rsurface.texture = R_GetCurrentTexture(texture);
11037                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11038                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11039                 {
11040                         // if this texture is not the kind we want, skip ahead to the next one
11041                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11042                                 ;
11043                         continue;
11044                 }
11045                 // simply scan ahead until we find a different texture or lightmap state
11046                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11047                         ;
11048                 // render the range of surfaces
11049                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11050         }
11051 }
11052
11053 float locboxvertex3f[6*4*3] =
11054 {
11055         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11056         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11057         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11058         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11059         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11060         1,0,0, 0,0,0, 0,1,0, 1,1,0
11061 };
11062
11063 unsigned short locboxelements[6*2*3] =
11064 {
11065          0, 1, 2, 0, 2, 3,
11066          4, 5, 6, 4, 6, 7,
11067          8, 9,10, 8,10,11,
11068         12,13,14, 12,14,15,
11069         16,17,18, 16,18,19,
11070         20,21,22, 20,22,23
11071 };
11072
11073 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11074 {
11075         int i, j;
11076         cl_locnode_t *loc = (cl_locnode_t *)ent;
11077         vec3_t mins, size;
11078         float vertex3f[6*4*3];
11079         CHECKGLERROR
11080         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11081         GL_DepthMask(false);
11082         GL_DepthRange(0, 1);
11083         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11084         GL_DepthTest(true);
11085         GL_CullFace(GL_NONE);
11086         R_EntityMatrix(&identitymatrix);
11087
11088         R_Mesh_VertexPointer(vertex3f, 0, 0);
11089         R_Mesh_ColorPointer(NULL, 0, 0);
11090         R_Mesh_ResetTextureState();
11091         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11092
11093         i = surfacelist[0];
11094         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11095                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11096                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11097                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11098
11099         if (VectorCompare(loc->mins, loc->maxs))
11100         {
11101                 VectorSet(size, 2, 2, 2);
11102                 VectorMA(loc->mins, -0.5f, size, mins);
11103         }
11104         else
11105         {
11106                 VectorCopy(loc->mins, mins);
11107                 VectorSubtract(loc->maxs, loc->mins, size);
11108         }
11109
11110         for (i = 0;i < 6*4*3;)
11111                 for (j = 0;j < 3;j++, i++)
11112                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11113
11114         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11115 }
11116
11117 void R_DrawLocs(void)
11118 {
11119         int index;
11120         cl_locnode_t *loc, *nearestloc;
11121         vec3_t center;
11122         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11123         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11124         {
11125                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11126                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11127         }
11128 }
11129
11130 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11131 {
11132         if (decalsystem->decals)
11133                 Mem_Free(decalsystem->decals);
11134         memset(decalsystem, 0, sizeof(*decalsystem));
11135 }
11136
11137 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)
11138 {
11139         tridecal_t *decal;
11140         tridecal_t *decals;
11141         int i;
11142         int maxdecals;
11143
11144         // expand or initialize the system
11145         if (decalsystem->maxdecals <= decalsystem->numdecals)
11146         {
11147                 decalsystem_t old = *decalsystem;
11148                 qboolean useshortelements;
11149                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11150                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11151                 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)));
11152                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11153                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11154                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11155                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11156                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11157                 if (decalsystem->numdecals)
11158                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11159                 if (old.decals)
11160                         Mem_Free(old.decals);
11161                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11162                         decalsystem->element3i[i] = i;
11163                 if (useshortelements)
11164                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11165                                 decalsystem->element3s[i] = i;
11166         }
11167
11168         // grab a decal and search for another free slot for the next one
11169         maxdecals = decalsystem->maxdecals;
11170         decals = decalsystem->decals;
11171         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11172         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11173                 ;
11174         decalsystem->freedecal = i;
11175         if (decalsystem->numdecals <= i)
11176                 decalsystem->numdecals = i + 1;
11177
11178         // initialize the decal
11179         decal->lived = 0;
11180         decal->triangleindex = triangleindex;
11181         decal->surfaceindex = surfaceindex;
11182         decal->decalsequence = decalsequence;
11183         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11184         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11185         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11186         decal->color4ub[0][3] = 255;
11187         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11188         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11189         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11190         decal->color4ub[1][3] = 255;
11191         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11192         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11193         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11194         decal->color4ub[2][3] = 255;
11195         decal->vertex3f[0][0] = v0[0];
11196         decal->vertex3f[0][1] = v0[1];
11197         decal->vertex3f[0][2] = v0[2];
11198         decal->vertex3f[1][0] = v1[0];
11199         decal->vertex3f[1][1] = v1[1];
11200         decal->vertex3f[1][2] = v1[2];
11201         decal->vertex3f[2][0] = v2[0];
11202         decal->vertex3f[2][1] = v2[1];
11203         decal->vertex3f[2][2] = v2[2];
11204         decal->texcoord2f[0][0] = t0[0];
11205         decal->texcoord2f[0][1] = t0[1];
11206         decal->texcoord2f[1][0] = t1[0];
11207         decal->texcoord2f[1][1] = t1[1];
11208         decal->texcoord2f[2][0] = t2[0];
11209         decal->texcoord2f[2][1] = t2[1];
11210 }
11211
11212 extern cvar_t cl_decals_bias;
11213 extern cvar_t cl_decals_models;
11214 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11215 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)
11216 {
11217         matrix4x4_t projection;
11218         decalsystem_t *decalsystem;
11219         qboolean dynamic;
11220         dp_model_t *model;
11221         const float *vertex3f;
11222         const msurface_t *surface;
11223         const msurface_t *surfaces;
11224         const int *surfacelist;
11225         const texture_t *texture;
11226         int numvertices;
11227         int numtriangles;
11228         int numsurfacelist;
11229         int surfacelistindex;
11230         int surfaceindex;
11231         int triangleindex;
11232         int decalsurfaceindex;
11233         int cornerindex;
11234         int index;
11235         int numpoints;
11236         const int *e;
11237         float localorigin[3];
11238         float localnormal[3];
11239         float localmins[3];
11240         float localmaxs[3];
11241         float localsize;
11242         float ilocalsize;
11243         float v[9][3];
11244         float tc[9][2];
11245         float c[9][4];
11246         //float normal[3];
11247         float planes[6][4];
11248         float f;
11249         float points[2][9][3];
11250         float angles[3];
11251         float temp[3];
11252
11253         decalsystem = &ent->decalsystem;
11254         model = ent->model;
11255         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11256         {
11257                 R_DecalSystem_Reset(&ent->decalsystem);
11258                 return;
11259         }
11260
11261         if (!model->brush.data_nodes && !cl_decals_models.integer)
11262         {
11263                 if (decalsystem->model)
11264                         R_DecalSystem_Reset(decalsystem);
11265                 return;
11266         }
11267
11268         if (decalsystem->model != model)
11269                 R_DecalSystem_Reset(decalsystem);
11270         decalsystem->model = model;
11271
11272         RSurf_ActiveModelEntity(ent, false, false, false);
11273
11274         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11275         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11276         VectorNormalize(localnormal);
11277         localsize = worldsize*rsurface.inversematrixscale;
11278         ilocalsize = 1.0f / localsize;
11279         localmins[0] = localorigin[0] - localsize;
11280         localmins[1] = localorigin[1] - localsize;
11281         localmins[2] = localorigin[2] - localsize;
11282         localmaxs[0] = localorigin[0] + localsize;
11283         localmaxs[1] = localorigin[1] + localsize;
11284         localmaxs[2] = localorigin[2] + localsize;
11285
11286         //VectorCopy(localnormal, planes[4]);
11287         //VectorVectors(planes[4], planes[2], planes[0]);
11288         AnglesFromVectors(angles, localnormal, NULL, false);
11289         AngleVectors(angles, planes[0], planes[2], planes[4]);
11290         VectorNegate(planes[0], planes[1]);
11291         VectorNegate(planes[2], planes[3]);
11292         VectorNegate(planes[4], planes[5]);
11293         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11294         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11295         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11296         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11297         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11298         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11299
11300 #if 1
11301 // works
11302 {
11303         matrix4x4_t forwardprojection;
11304         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11305         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11306 }
11307 #else
11308 // broken
11309 {
11310         float projectionvector[4][3];
11311         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11312         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11313         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11314         projectionvector[0][0] = planes[0][0] * ilocalsize;
11315         projectionvector[0][1] = planes[1][0] * ilocalsize;
11316         projectionvector[0][2] = planes[2][0] * ilocalsize;
11317         projectionvector[1][0] = planes[0][1] * ilocalsize;
11318         projectionvector[1][1] = planes[1][1] * ilocalsize;
11319         projectionvector[1][2] = planes[2][1] * ilocalsize;
11320         projectionvector[2][0] = planes[0][2] * ilocalsize;
11321         projectionvector[2][1] = planes[1][2] * ilocalsize;
11322         projectionvector[2][2] = planes[2][2] * ilocalsize;
11323         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11324         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11325         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11326         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11327 }
11328 #endif
11329
11330         dynamic = model->surfmesh.isanimated;
11331         vertex3f = rsurface.modelvertex3f;
11332         numsurfacelist = model->nummodelsurfaces;
11333         surfacelist = model->sortedmodelsurfaces;
11334         surfaces = model->data_surfaces;
11335         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11336         {
11337                 surfaceindex = surfacelist[surfacelistindex];
11338                 surface = surfaces + surfaceindex;
11339                 // skip transparent surfaces
11340                 texture = surface->texture;
11341                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11342                         continue;
11343                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11344                         continue;
11345                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11346                         continue;
11347                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11348                 numvertices = surface->num_vertices;
11349                 numtriangles = surface->num_triangles;
11350                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11351                 {
11352                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11353                         {
11354                                 index = 3*e[cornerindex];
11355                                 VectorCopy(vertex3f + index, v[cornerindex]);
11356                         }
11357                         // cull backfaces
11358                         //TriangleNormal(v[0], v[1], v[2], normal);
11359                         //if (DotProduct(normal, localnormal) < 0.0f)
11360                         //      continue;
11361                         // clip by each of the box planes formed from the projection matrix
11362                         // if anything survives, we emit the decal
11363                         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]);
11364                         if (numpoints < 3)
11365                                 continue;
11366                         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]);
11367                         if (numpoints < 3)
11368                                 continue;
11369                         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]);
11370                         if (numpoints < 3)
11371                                 continue;
11372                         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]);
11373                         if (numpoints < 3)
11374                                 continue;
11375                         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]);
11376                         if (numpoints < 3)
11377                                 continue;
11378                         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]);
11379                         if (numpoints < 3)
11380                                 continue;
11381                         // some part of the triangle survived, so we have to accept it...
11382                         if (dynamic)
11383                         {
11384                                 // dynamic always uses the original triangle
11385                                 numpoints = 3;
11386                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11387                                 {
11388                                         index = 3*e[cornerindex];
11389                                         VectorCopy(vertex3f + index, v[cornerindex]);
11390                                 }
11391                         }
11392                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11393                         {
11394                                 // convert vertex positions to texcoords
11395                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11396                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11397                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11398                                 // calculate distance fade from the projection origin
11399                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11400                                 f = bound(0.0f, f, 1.0f);
11401                                 c[cornerindex][0] = r * f;
11402                                 c[cornerindex][1] = g * f;
11403                                 c[cornerindex][2] = b * f;
11404                                 c[cornerindex][3] = 1.0f;
11405                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11406                         }
11407                         if (dynamic)
11408                                 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);
11409                         else
11410                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11411                                         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);
11412                 }
11413         }
11414 }
11415
11416 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11417 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)
11418 {
11419         int renderentityindex;
11420         float worldmins[3];
11421         float worldmaxs[3];
11422         entity_render_t *ent;
11423
11424         if (!cl_decals_newsystem.integer)
11425                 return;
11426
11427         worldmins[0] = worldorigin[0] - worldsize;
11428         worldmins[1] = worldorigin[1] - worldsize;
11429         worldmins[2] = worldorigin[2] - worldsize;
11430         worldmaxs[0] = worldorigin[0] + worldsize;
11431         worldmaxs[1] = worldorigin[1] + worldsize;
11432         worldmaxs[2] = worldorigin[2] + worldsize;
11433
11434         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11435
11436         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11437         {
11438                 ent = r_refdef.scene.entities[renderentityindex];
11439                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11440                         continue;
11441
11442                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11443         }
11444 }
11445
11446 typedef struct r_decalsystem_splatqueue_s
11447 {
11448         vec3_t worldorigin;
11449         vec3_t worldnormal;
11450         float color[4];
11451         float tcrange[4];
11452         float worldsize;
11453         int decalsequence;
11454 }
11455 r_decalsystem_splatqueue_t;
11456
11457 int r_decalsystem_numqueued = 0;
11458 #define MAX_DECALSYSTEM_QUEUE 1024
11459 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11460
11461 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)
11462 {
11463         r_decalsystem_splatqueue_t *queue;
11464
11465         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11466                 return;
11467
11468         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11469         VectorCopy(worldorigin, queue->worldorigin);
11470         VectorCopy(worldnormal, queue->worldnormal);
11471         Vector4Set(queue->color, r, g, b, a);
11472         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11473         queue->worldsize = worldsize;
11474         queue->decalsequence = cl.decalsequence++;
11475 }
11476
11477 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11478 {
11479         int i;
11480         r_decalsystem_splatqueue_t *queue;
11481
11482         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11483                 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);
11484         r_decalsystem_numqueued = 0;
11485 }
11486
11487 extern cvar_t cl_decals_max;
11488 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11489 {
11490         int i;
11491         decalsystem_t *decalsystem = &ent->decalsystem;
11492         int numdecals;
11493         int killsequence;
11494         tridecal_t *decal;
11495         float frametime;
11496         float lifetime;
11497
11498         if (!decalsystem->numdecals)
11499                 return;
11500
11501         if (r_showsurfaces.integer)
11502                 return;
11503
11504         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11505         {
11506                 R_DecalSystem_Reset(decalsystem);
11507                 return;
11508         }
11509
11510         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11511         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11512
11513         if (decalsystem->lastupdatetime)
11514                 frametime = (cl.time - decalsystem->lastupdatetime);
11515         else
11516                 frametime = 0;
11517         decalsystem->lastupdatetime = cl.time;
11518         decal = decalsystem->decals;
11519         numdecals = decalsystem->numdecals;
11520
11521         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11522         {
11523                 if (decal->color4ub[0][3])
11524                 {
11525                         decal->lived += frametime;
11526                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11527                         {
11528                                 memset(decal, 0, sizeof(*decal));
11529                                 if (decalsystem->freedecal > i)
11530                                         decalsystem->freedecal = i;
11531                         }
11532                 }
11533         }
11534         decal = decalsystem->decals;
11535         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11536                 numdecals--;
11537
11538         // collapse the array by shuffling the tail decals into the gaps
11539         for (;;)
11540         {
11541                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11542                         decalsystem->freedecal++;
11543                 if (decalsystem->freedecal == numdecals)
11544                         break;
11545                 decal[decalsystem->freedecal] = decal[--numdecals];
11546         }
11547
11548         decalsystem->numdecals = numdecals;
11549
11550         if (numdecals <= 0)
11551         {
11552                 // if there are no decals left, reset decalsystem
11553                 R_DecalSystem_Reset(decalsystem);
11554         }
11555 }
11556
11557 extern skinframe_t *decalskinframe;
11558 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11559 {
11560         int i;
11561         decalsystem_t *decalsystem = &ent->decalsystem;
11562         int numdecals;
11563         tridecal_t *decal;
11564         float fadedelay;
11565         float faderate;
11566         float alpha;
11567         float *v3f;
11568         float *c4f;
11569         float *t2f;
11570         const int *e;
11571         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11572         int numtris = 0;
11573
11574         numdecals = decalsystem->numdecals;
11575         if (!numdecals)
11576                 return;
11577
11578         if (r_showsurfaces.integer)
11579                 return;
11580
11581         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11582         {
11583                 R_DecalSystem_Reset(decalsystem);
11584                 return;
11585         }
11586
11587         // if the model is static it doesn't matter what value we give for
11588         // wantnormals and wanttangents, so this logic uses only rules applicable
11589         // to a model, knowing that they are meaningless otherwise
11590         if (ent == r_refdef.scene.worldentity)
11591                 RSurf_ActiveWorldEntity();
11592         else
11593                 RSurf_ActiveModelEntity(ent, false, false, false);
11594
11595         decalsystem->lastupdatetime = cl.time;
11596         decal = decalsystem->decals;
11597
11598         fadedelay = cl_decals_time.value;
11599         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11600
11601         // update vertex positions for animated models
11602         v3f = decalsystem->vertex3f;
11603         c4f = decalsystem->color4f;
11604         t2f = decalsystem->texcoord2f;
11605         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11606         {
11607                 if (!decal->color4ub[0][3])
11608                         continue;
11609
11610                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11611                         continue;
11612
11613                 // update color values for fading decals
11614                 if (decal->lived >= cl_decals_time.value)
11615                 {
11616                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11617                         alpha *= (1.0f/255.0f);
11618                 }
11619                 else
11620                         alpha = 1.0f/255.0f;
11621
11622                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11623                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11624                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11625                 c4f[ 3] = 1;
11626                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11627                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11628                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11629                 c4f[ 7] = 1;
11630                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11631                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11632                 c4f[10] = decal->color4ub[2][2] * alpha;
11633                 c4f[11] = 1;
11634
11635                 t2f[0] = decal->texcoord2f[0][0];
11636                 t2f[1] = decal->texcoord2f[0][1];
11637                 t2f[2] = decal->texcoord2f[1][0];
11638                 t2f[3] = decal->texcoord2f[1][1];
11639                 t2f[4] = decal->texcoord2f[2][0];
11640                 t2f[5] = decal->texcoord2f[2][1];
11641
11642                 // update vertex positions for animated models
11643                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11644                 {
11645                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11646                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11647                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11648                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11649                 }
11650                 else
11651                 {
11652                         VectorCopy(decal->vertex3f[0], v3f);
11653                         VectorCopy(decal->vertex3f[1], v3f + 3);
11654                         VectorCopy(decal->vertex3f[2], v3f + 6);
11655                 }
11656
11657                 v3f += 9;
11658                 c4f += 12;
11659                 t2f += 6;
11660                 numtris++;
11661         }
11662
11663         if (numtris > 0)
11664         {
11665                 r_refdef.stats.drawndecals += numtris;
11666
11667                 if (r_refdef.fogenabled)
11668                 {
11669                         switch(vid.renderpath)
11670                         {
11671                         case RENDERPATH_GL20:
11672                         case RENDERPATH_CGGL:
11673                         case RENDERPATH_GL13:
11674                         case RENDERPATH_GL11:
11675                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11676                                 {
11677                                         alpha = RSurf_FogVertex(v3f);
11678                                         c4f[0] *= alpha;
11679                                         c4f[1] *= alpha;
11680                                         c4f[2] *= alpha;
11681                                 }
11682                                 break;
11683                         }
11684                 }
11685
11686                 // now render the decals all at once
11687                 // (this assumes they all use one particle font texture!)
11688                 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);
11689                 R_Mesh_ResetTextureState();
11690                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11691                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11692                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11693                 GL_DepthMask(false);
11694                 GL_DepthRange(0, 1);
11695                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11696                 GL_DepthTest(true);
11697                 GL_CullFace(GL_NONE);
11698                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11699                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11700                 GL_LockArrays(0, numtris * 3);
11701                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11702                 GL_LockArrays(0, 0);
11703         }
11704 }
11705
11706 static void R_DrawModelDecals(void)
11707 {
11708         int i, numdecals;
11709
11710         // fade faster when there are too many decals
11711         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11712         for (i = 0;i < r_refdef.scene.numentities;i++)
11713                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11714
11715         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11716         for (i = 0;i < r_refdef.scene.numentities;i++)
11717                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11718                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11719
11720         R_DecalSystem_ApplySplatEntitiesQueue();
11721
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_refdef.stats.totaldecals += numdecals;
11727
11728         if (r_showsurfaces.integer)
11729                 return;
11730
11731         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11732
11733         for (i = 0;i < r_refdef.scene.numentities;i++)
11734         {
11735                 if (!r_refdef.viewcache.entityvisible[i])
11736                         continue;
11737                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11738                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11739         }
11740 }
11741
11742 void R_DrawDebugModel(void)
11743 {
11744         entity_render_t *ent = rsurface.entity;
11745         int i, j, k, l, flagsmask;
11746         const int *elements;
11747         q3mbrush_t *brush;
11748         const msurface_t *surface;
11749         dp_model_t *model = ent->model;
11750         vec3_t v;
11751
11752         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11753
11754         R_Mesh_ColorPointer(NULL, 0, 0);
11755         R_Mesh_ResetTextureState();
11756         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11757         GL_DepthRange(0, 1);
11758         GL_DepthTest(!r_showdisabledepthtest.integer);
11759         GL_DepthMask(false);
11760         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11761
11762         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11763         {
11764                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11765                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11766                 {
11767                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11768                         {
11769                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11770                                 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);
11771                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11772                         }
11773                 }
11774                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11775                 {
11776                         if (surface->num_collisiontriangles)
11777                         {
11778                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11779                                 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);
11780                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11781                         }
11782                 }
11783         }
11784
11785         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11786
11787         if (r_showtris.integer || r_shownormals.integer)
11788         {
11789                 if (r_showdisabledepthtest.integer)
11790                 {
11791                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11792                         GL_DepthMask(false);
11793                 }
11794                 else
11795                 {
11796                         GL_BlendFunc(GL_ONE, GL_ZERO);
11797                         GL_DepthMask(true);
11798                 }
11799                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11800                 {
11801                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11802                                 continue;
11803                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11804                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11805                         {
11806                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11807                                 if (r_showtris.value > 0)
11808                                 {
11809                                         if (!rsurface.texture->currentlayers->depthmask)
11810                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11811                                         else if (ent == r_refdef.scene.worldentity)
11812                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11813                                         else
11814                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11815                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11816                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11817                                         R_Mesh_ColorPointer(NULL, 0, 0);
11818                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11819                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11820                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11821                                         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);
11822                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11823                                         CHECKGLERROR
11824                                 }
11825                                 if (r_shownormals.value < 0)
11826                                 {
11827                                         qglBegin(GL_LINES);
11828                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11829                                         {
11830                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11831                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11832                                                 qglVertex3f(v[0], v[1], v[2]);
11833                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11834                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11835                                                 qglVertex3f(v[0], v[1], v[2]);
11836                                         }
11837                                         qglEnd();
11838                                         CHECKGLERROR
11839                                 }
11840                                 if (r_shownormals.value > 0)
11841                                 {
11842                                         qglBegin(GL_LINES);
11843                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11844                                         {
11845                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11846                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11847                                                 qglVertex3f(v[0], v[1], v[2]);
11848                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11849                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11850                                                 qglVertex3f(v[0], v[1], v[2]);
11851                                         }
11852                                         qglEnd();
11853                                         CHECKGLERROR
11854                                         qglBegin(GL_LINES);
11855                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11856                                         {
11857                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11858                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11859                                                 qglVertex3f(v[0], v[1], v[2]);
11860                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11861                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11862                                                 qglVertex3f(v[0], v[1], v[2]);
11863                                         }
11864                                         qglEnd();
11865                                         CHECKGLERROR
11866                                         qglBegin(GL_LINES);
11867                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11868                                         {
11869                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11870                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11871                                                 qglVertex3f(v[0], v[1], v[2]);
11872                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11873                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11874                                                 qglVertex3f(v[0], v[1], v[2]);
11875                                         }
11876                                         qglEnd();
11877                                         CHECKGLERROR
11878                                 }
11879                         }
11880                 }
11881                 rsurface.texture = NULL;
11882         }
11883 }
11884
11885 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11886 int r_maxsurfacelist = 0;
11887 const msurface_t **r_surfacelist = NULL;
11888 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11889 {
11890         int i, j, endj, f, flagsmask;
11891         texture_t *t;
11892         dp_model_t *model = r_refdef.scene.worldmodel;
11893         msurface_t *surfaces;
11894         unsigned char *update;
11895         int numsurfacelist = 0;
11896         if (model == NULL)
11897                 return;
11898
11899         if (r_maxsurfacelist < model->num_surfaces)
11900         {
11901                 r_maxsurfacelist = model->num_surfaces;
11902                 if (r_surfacelist)
11903                         Mem_Free((msurface_t**)r_surfacelist);
11904                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11905         }
11906
11907         RSurf_ActiveWorldEntity();
11908
11909         surfaces = model->data_surfaces;
11910         update = model->brushq1.lightmapupdateflags;
11911
11912         // update light styles on this submodel
11913         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11914         {
11915                 model_brush_lightstyleinfo_t *style;
11916                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11917                 {
11918                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11919                         {
11920                                 int *list = style->surfacelist;
11921                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11922                                 for (j = 0;j < style->numsurfaces;j++)
11923                                         update[list[j]] = true;
11924                         }
11925                 }
11926         }
11927
11928         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11929
11930         if (debug)
11931         {
11932                 R_DrawDebugModel();
11933                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11934                 return;
11935         }
11936
11937         f = 0;
11938         t = NULL;
11939         rsurface.uselightmaptexture = false;
11940         rsurface.texture = NULL;
11941         rsurface.rtlight = NULL;
11942         numsurfacelist = 0;
11943         // add visible surfaces to draw list
11944         for (i = 0;i < model->nummodelsurfaces;i++)
11945         {
11946                 j = model->sortedmodelsurfaces[i];
11947                 if (r_refdef.viewcache.world_surfacevisible[j])
11948                         r_surfacelist[numsurfacelist++] = surfaces + j;
11949         }
11950         // update lightmaps if needed
11951         if (model->brushq1.firstrender)
11952         {
11953                 model->brushq1.firstrender = false;
11954                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11955                         if (update[j])
11956                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11957         }
11958         else if (update)
11959         {
11960                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11961                         if (r_refdef.viewcache.world_surfacevisible[j])
11962                                 if (update[j])
11963                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11964         }
11965         // don't do anything if there were no surfaces
11966         if (!numsurfacelist)
11967         {
11968                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11969                 return;
11970         }
11971         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11972         GL_AlphaTest(false);
11973
11974         // add to stats if desired
11975         if (r_speeds.integer && !skysurfaces && !depthonly)
11976         {
11977                 r_refdef.stats.world_surfaces += numsurfacelist;
11978                 for (j = 0;j < numsurfacelist;j++)
11979                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11980         }
11981
11982         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11983 }
11984
11985 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11986 {
11987         int i, j, endj, f, flagsmask;
11988         texture_t *t;
11989         dp_model_t *model = ent->model;
11990         msurface_t *surfaces;
11991         unsigned char *update;
11992         int numsurfacelist = 0;
11993         if (model == NULL)
11994                 return;
11995
11996         if (r_maxsurfacelist < model->num_surfaces)
11997         {
11998                 r_maxsurfacelist = model->num_surfaces;
11999                 if (r_surfacelist)
12000                         Mem_Free((msurface_t **)r_surfacelist);
12001                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12002         }
12003
12004         // if the model is static it doesn't matter what value we give for
12005         // wantnormals and wanttangents, so this logic uses only rules applicable
12006         // to a model, knowing that they are meaningless otherwise
12007         if (ent == r_refdef.scene.worldentity)
12008                 RSurf_ActiveWorldEntity();
12009         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12010                 RSurf_ActiveModelEntity(ent, false, false, false);
12011         else if (prepass)
12012                 RSurf_ActiveModelEntity(ent, true, true, true);
12013         else if (depthonly)
12014                 RSurf_ActiveModelEntity(ent, false, false, false);
12015         else
12016         {
12017                 switch (vid.renderpath)
12018                 {
12019                 case RENDERPATH_GL20:
12020                 case RENDERPATH_CGGL:
12021                         RSurf_ActiveModelEntity(ent, true, true, false);
12022                         break;
12023                 case RENDERPATH_GL13:
12024                 case RENDERPATH_GL11:
12025                         RSurf_ActiveModelEntity(ent, true, false, false);
12026                         break;
12027                 }
12028         }
12029
12030         surfaces = model->data_surfaces;
12031         update = model->brushq1.lightmapupdateflags;
12032
12033         // update light styles
12034         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12035         {
12036                 model_brush_lightstyleinfo_t *style;
12037                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12038                 {
12039                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12040                         {
12041                                 int *list = style->surfacelist;
12042                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12043                                 for (j = 0;j < style->numsurfaces;j++)
12044                                         update[list[j]] = true;
12045                         }
12046                 }
12047         }
12048
12049         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12050
12051         if (debug)
12052         {
12053                 R_DrawDebugModel();
12054                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12055                 return;
12056         }
12057
12058         f = 0;
12059         t = NULL;
12060         rsurface.uselightmaptexture = false;
12061         rsurface.texture = NULL;
12062         rsurface.rtlight = NULL;
12063         numsurfacelist = 0;
12064         // add visible surfaces to draw list
12065         for (i = 0;i < model->nummodelsurfaces;i++)
12066                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12067         // don't do anything if there were no surfaces
12068         if (!numsurfacelist)
12069         {
12070                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12071                 return;
12072         }
12073         // update lightmaps if needed
12074         if (update)
12075         {
12076                 int updated = 0;
12077                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12078                 {
12079                         if (update[j])
12080                         {
12081                                 updated++;
12082                                 R_BuildLightMap(ent, surfaces + j);
12083                         }
12084                 }
12085         }
12086         if (update)
12087                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12088                         if (update[j])
12089                                 R_BuildLightMap(ent, surfaces + j);
12090         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12091         GL_AlphaTest(false);
12092
12093         // add to stats if desired
12094         if (r_speeds.integer && !skysurfaces && !depthonly)
12095         {
12096                 r_refdef.stats.entities_surfaces += numsurfacelist;
12097                 for (j = 0;j < numsurfacelist;j++)
12098                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12099         }
12100
12101         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12102 }
12103
12104 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12105 {
12106         static texture_t texture;
12107         static msurface_t surface;
12108         const msurface_t *surfacelist = &surface;
12109
12110         // fake enough texture and surface state to render this geometry
12111
12112         texture.update_lastrenderframe = -1; // regenerate this texture
12113         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12114         texture.currentskinframe = skinframe;
12115         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12116         texture.specularscalemod = 1;
12117         texture.specularpowermod = 1;
12118
12119         surface.texture = &texture;
12120         surface.num_triangles = numtriangles;
12121         surface.num_firsttriangle = firsttriangle;
12122         surface.num_vertices = numvertices;
12123         surface.num_firstvertex = firstvertex;
12124
12125         // now render it
12126         rsurface.texture = R_GetCurrentTexture(surface.texture);
12127         rsurface.uselightmaptexture = false;
12128         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12129 }
12130
12131 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)
12132 {
12133         static msurface_t surface;
12134         const msurface_t *surfacelist = &surface;
12135
12136         // fake enough texture and surface state to render this geometry
12137
12138         surface.texture = texture;
12139         surface.num_triangles = numtriangles;
12140         surface.num_firsttriangle = firsttriangle;
12141         surface.num_vertices = numvertices;
12142         surface.num_firstvertex = firstvertex;
12143
12144         // now render it
12145         rsurface.texture = R_GetCurrentTexture(surface.texture);
12146         rsurface.uselightmaptexture = false;
12147         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12148 }