]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
moved R_Mesh_TexCoordPointer, R_Mesh_ColorPointer, GL_BlendFunc, and
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_frame = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
73 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
74 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
96 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
102
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
111
112 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
113 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
114
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
118
119 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
125 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
126 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
127 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
128
129 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
134
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
139
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
147
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
152
153 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
154
155 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
156
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
158
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
166
167 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
168
169 extern cvar_t v_glslgamma;
170
171 extern qboolean v_flipped_state;
172
173 static struct r_bloomstate_s
174 {
175         qboolean enabled;
176         qboolean hdr;
177
178         int bloomwidth, bloomheight;
179
180         int screentexturewidth, screentextureheight;
181         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
182
183         int bloomtexturewidth, bloomtextureheight;
184         rtexture_t *texture_bloom;
185
186         // arrays for rendering the screen passes
187         float screentexcoord2f[8];
188         float bloomtexcoord2f[8];
189         float offsettexcoord2f[8];
190
191         r_viewport_t viewport;
192 }
193 r_bloomstate;
194
195 r_waterstate_t r_waterstate;
196
197 /// shadow volume bsp struct with automatically growing nodes buffer
198 svbsp_t r_svbsp;
199
200 rtexture_t *r_texture_blanknormalmap;
201 rtexture_t *r_texture_white;
202 rtexture_t *r_texture_grey128;
203 rtexture_t *r_texture_black;
204 rtexture_t *r_texture_notexture;
205 rtexture_t *r_texture_whitecube;
206 rtexture_t *r_texture_normalizationcube;
207 rtexture_t *r_texture_fogattenuation;
208 rtexture_t *r_texture_gammaramps;
209 unsigned int r_texture_gammaramps_serial;
210 //rtexture_t *r_texture_fogintensity;
211
212 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
213 unsigned int r_numqueries;
214 unsigned int r_maxqueries;
215
216 typedef struct r_qwskincache_s
217 {
218         char name[MAX_QPATH];
219         skinframe_t *skinframe;
220 }
221 r_qwskincache_t;
222
223 static r_qwskincache_t *r_qwskincache;
224 static int r_qwskincache_size;
225
226 /// vertex coordinates for a quad that covers the screen exactly
227 const float r_screenvertex3f[12] =
228 {
229         0, 0, 0,
230         1, 0, 0,
231         1, 1, 0,
232         0, 1, 0
233 };
234
235 extern void R_DrawModelShadows(void);
236
237 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
238 {
239         int i;
240         for (i = 0;i < verts;i++)
241         {
242                 out[0] = in[0] * r;
243                 out[1] = in[1] * g;
244                 out[2] = in[2] * b;
245                 out[3] = in[3];
246                 in += 4;
247                 out += 4;
248         }
249 }
250
251 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
252 {
253         int i;
254         for (i = 0;i < verts;i++)
255         {
256                 out[0] = r;
257                 out[1] = g;
258                 out[2] = b;
259                 out[3] = a;
260                 out += 4;
261         }
262 }
263
264 // FIXME: move this to client?
265 void FOG_clear(void)
266 {
267         if (gamemode == GAME_NEHAHRA)
268         {
269                 Cvar_Set("gl_fogenable", "0");
270                 Cvar_Set("gl_fogdensity", "0.2");
271                 Cvar_Set("gl_fogred", "0.3");
272                 Cvar_Set("gl_foggreen", "0.3");
273                 Cvar_Set("gl_fogblue", "0.3");
274         }
275         r_refdef.fog_density = 0;
276         r_refdef.fog_red = 0;
277         r_refdef.fog_green = 0;
278         r_refdef.fog_blue = 0;
279         r_refdef.fog_alpha = 1;
280         r_refdef.fog_start = 0;
281         r_refdef.fog_end = 16384;
282         r_refdef.fog_height = 1<<30;
283         r_refdef.fog_fadedepth = 128;
284 }
285
286 static void R_BuildBlankTextures(void)
287 {
288         unsigned char data[4];
289         data[2] = 128; // normal X
290         data[1] = 128; // normal Y
291         data[0] = 255; // normal Z
292         data[3] = 128; // height
293         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
294         data[0] = 255;
295         data[1] = 255;
296         data[2] = 255;
297         data[3] = 255;
298         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
299         data[0] = 128;
300         data[1] = 128;
301         data[2] = 128;
302         data[3] = 255;
303         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
304         data[0] = 0;
305         data[1] = 0;
306         data[2] = 0;
307         data[3] = 255;
308         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
309 }
310
311 static void R_BuildNoTexture(void)
312 {
313         int x, y;
314         unsigned char pix[16][16][4];
315         // this makes a light grey/dark grey checkerboard texture
316         for (y = 0;y < 16;y++)
317         {
318                 for (x = 0;x < 16;x++)
319                 {
320                         if ((y < 8) ^ (x < 8))
321                         {
322                                 pix[y][x][0] = 128;
323                                 pix[y][x][1] = 128;
324                                 pix[y][x][2] = 128;
325                                 pix[y][x][3] = 255;
326                         }
327                         else
328                         {
329                                 pix[y][x][0] = 64;
330                                 pix[y][x][1] = 64;
331                                 pix[y][x][2] = 64;
332                                 pix[y][x][3] = 255;
333                         }
334                 }
335         }
336         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
337 }
338
339 static void R_BuildWhiteCube(void)
340 {
341         unsigned char data[6*1*1*4];
342         memset(data, 255, sizeof(data));
343         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
344 }
345
346 static void R_BuildNormalizationCube(void)
347 {
348         int x, y, side;
349         vec3_t v;
350         vec_t s, t, intensity;
351 #define NORMSIZE 64
352         unsigned char *data;
353         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
354         for (side = 0;side < 6;side++)
355         {
356                 for (y = 0;y < NORMSIZE;y++)
357                 {
358                         for (x = 0;x < NORMSIZE;x++)
359                         {
360                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
361                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
362                                 switch(side)
363                                 {
364                                 default:
365                                 case 0:
366                                         v[0] = 1;
367                                         v[1] = -t;
368                                         v[2] = -s;
369                                         break;
370                                 case 1:
371                                         v[0] = -1;
372                                         v[1] = -t;
373                                         v[2] = s;
374                                         break;
375                                 case 2:
376                                         v[0] = s;
377                                         v[1] = 1;
378                                         v[2] = t;
379                                         break;
380                                 case 3:
381                                         v[0] = s;
382                                         v[1] = -1;
383                                         v[2] = -t;
384                                         break;
385                                 case 4:
386                                         v[0] = s;
387                                         v[1] = -t;
388                                         v[2] = 1;
389                                         break;
390                                 case 5:
391                                         v[0] = -s;
392                                         v[1] = -t;
393                                         v[2] = -1;
394                                         break;
395                                 }
396                                 intensity = 127.0f / sqrt(DotProduct(v, v));
397                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
398                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
399                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
400                                 data[((side*64+y)*64+x)*4+3] = 255;
401                         }
402                 }
403         }
404         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
405         Mem_Free(data);
406 }
407
408 static void R_BuildFogTexture(void)
409 {
410         int x, b;
411 #define FOGWIDTH 256
412         unsigned char data1[FOGWIDTH][4];
413         //unsigned char data2[FOGWIDTH][4];
414         double d, r, alpha;
415
416         r_refdef.fogmasktable_start = r_refdef.fog_start;
417         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
418         r_refdef.fogmasktable_range = r_refdef.fogrange;
419         r_refdef.fogmasktable_density = r_refdef.fog_density;
420
421         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
422         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
423         {
424                 d = (x * r - r_refdef.fogmasktable_start);
425                 if(developer_extra.integer)
426                         Con_DPrintf("%f ", d);
427                 d = max(0, d);
428                 if (r_fog_exp2.integer)
429                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
430                 else
431                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
432                 if(developer_extra.integer)
433                         Con_DPrintf(" : %f ", alpha);
434                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
435                 if(developer_extra.integer)
436                         Con_DPrintf(" = %f\n", alpha);
437                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
438         }
439
440         for (x = 0;x < FOGWIDTH;x++)
441         {
442                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
443                 data1[x][0] = b;
444                 data1[x][1] = b;
445                 data1[x][2] = b;
446                 data1[x][3] = 255;
447                 //data2[x][0] = 255 - b;
448                 //data2[x][1] = 255 - b;
449                 //data2[x][2] = 255 - b;
450                 //data2[x][3] = 255;
451         }
452         if (r_texture_fogattenuation)
453         {
454                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
455                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
456         }
457         else
458         {
459                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
460                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
461         }
462 }
463
464 //=======================================================================================================================================================
465
466 static const char *builtinshaderstring =
467 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
468 "// written by Forest 'LordHavoc' Hale\n"
469 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
470 "\n"
471 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
472 "# define USEFOG\n"
473 "#endif\n"
474 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
475 "#define USELIGHTMAP\n"
476 "#endif\n"
477 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
478 "#define USEEYEVECTOR\n"
479 "#endif\n"
480 "\n"
481 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
482 "# extension GL_ARB_texture_rectangle : enable\n"
483 "#endif\n"
484 "\n"
485 "#ifdef USESHADOWMAP2D\n"
486 "# ifdef GL_EXT_gpu_shader4\n"
487 "#   extension GL_EXT_gpu_shader4 : enable\n"
488 "# endif\n"
489 "# ifdef GL_ARB_texture_gather\n"
490 "#   extension GL_ARB_texture_gather : enable\n"
491 "# else\n"
492 "#   ifdef GL_AMD_texture_texture4\n"
493 "#     extension GL_AMD_texture_texture4 : enable\n"
494 "#   endif\n"
495 "# endif\n"
496 "#endif\n"
497 "\n"
498 "#ifdef USESHADOWMAPCUBE\n"
499 "# extension GL_EXT_gpu_shader4 : enable\n"
500 "#endif\n"
501 "\n"
502 "//#ifdef USESHADOWSAMPLER\n"
503 "//# extension GL_ARB_shadow : enable\n"
504 "//#endif\n"
505 "\n"
506 "//#ifdef __GLSL_CG_DATA_TYPES\n"
507 "//# define myhalf half\n"
508 "//# define myhalf2 half2\n"
509 "//# define myhalf3 half3\n"
510 "//# define myhalf4 half4\n"
511 "//#else\n"
512 "# define myhalf float\n"
513 "# define myhalf2 vec2\n"
514 "# define myhalf3 vec3\n"
515 "# define myhalf4 vec4\n"
516 "//#endif\n"
517 "\n"
518 "#ifdef VERTEX_SHADER\n"
519 "uniform mat4 ModelViewProjectionMatrix;\n"
520 "#endif\n"
521 "\n"
522 "#ifdef MODE_DEPTH_OR_SHADOW\n"
523 "#ifdef VERTEX_SHADER\n"
524 "void main(void)\n"
525 "{\n"
526 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
527 "}\n"
528 "#endif\n"
529 "#else // !MODE_DEPTH_ORSHADOW\n"
530 "\n"
531 "\n"
532 "\n"
533 "\n"
534 "#ifdef MODE_SHOWDEPTH\n"
535 "#ifdef VERTEX_SHADER\n"
536 "void main(void)\n"
537 "{\n"
538 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
539 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
540 "}\n"
541 "#endif\n"
542 "\n"
543 "#ifdef FRAGMENT_SHADER\n"
544 "void main(void)\n"
545 "{\n"
546 "       gl_FragColor = gl_Color;\n"
547 "}\n"
548 "#endif\n"
549 "#else // !MODE_SHOWDEPTH\n"
550 "\n"
551 "\n"
552 "\n"
553 "\n"
554 "#ifdef MODE_POSTPROCESS\n"
555 "varying vec2 TexCoord1;\n"
556 "varying vec2 TexCoord2;\n"
557 "\n"
558 "#ifdef VERTEX_SHADER\n"
559 "void main(void)\n"
560 "{\n"
561 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
562 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
563 "#ifdef USEBLOOM\n"
564 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
565 "#endif\n"
566 "}\n"
567 "#endif\n"
568 "\n"
569 "#ifdef FRAGMENT_SHADER\n"
570 "uniform sampler2D Texture_First;\n"
571 "#ifdef USEBLOOM\n"
572 "uniform sampler2D Texture_Second;\n"
573 "#endif\n"
574 "#ifdef USEGAMMARAMPS\n"
575 "uniform sampler2D Texture_GammaRamps;\n"
576 "#endif\n"
577 "#ifdef USESATURATION\n"
578 "uniform float Saturation;\n"
579 "#endif\n"
580 "#ifdef USEVIEWTINT\n"
581 "uniform vec4 ViewTintColor;\n"
582 "#endif\n"
583 "//uncomment these if you want to use them:\n"
584 "uniform vec4 UserVec1;\n"
585 "// uniform vec4 UserVec2;\n"
586 "// uniform vec4 UserVec3;\n"
587 "// uniform vec4 UserVec4;\n"
588 "// uniform float ClientTime;\n"
589 "uniform vec2 PixelSize;\n"
590 "void main(void)\n"
591 "{\n"
592 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
593 "#ifdef USEBLOOM\n"
594 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
595 "#endif\n"
596 "#ifdef USEVIEWTINT\n"
597 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
598 "#endif\n"
599 "\n"
600 "#ifdef USEPOSTPROCESSING\n"
601 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
602 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
603 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
604 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
605 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
606 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
607 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
608 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
609 "#endif\n"
610 "\n"
611 "#ifdef USESATURATION\n"
612 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
613 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
614 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
615 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
616 "#endif\n"
617 "\n"
618 "#ifdef USEGAMMARAMPS\n"
619 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
620 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
621 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
622 "#endif\n"
623 "}\n"
624 "#endif\n"
625 "#else // !MODE_POSTPROCESS\n"
626 "\n"
627 "\n"
628 "\n"
629 "\n"
630 "#ifdef MODE_GENERIC\n"
631 "#ifdef USEDIFFUSE\n"
632 "varying vec2 TexCoord1;\n"
633 "#endif\n"
634 "#ifdef USESPECULAR\n"
635 "varying vec2 TexCoord2;\n"
636 "#endif\n"
637 "#ifdef VERTEX_SHADER\n"
638 "void main(void)\n"
639 "{\n"
640 "       gl_FrontColor = gl_Color;\n"
641 "#ifdef USEDIFFUSE\n"
642 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
643 "#endif\n"
644 "#ifdef USESPECULAR\n"
645 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
646 "#endif\n"
647 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
648 "}\n"
649 "#endif\n"
650 "\n"
651 "#ifdef FRAGMENT_SHADER\n"
652 "#ifdef USEDIFFUSE\n"
653 "uniform sampler2D Texture_First;\n"
654 "#endif\n"
655 "#ifdef USESPECULAR\n"
656 "uniform sampler2D Texture_Second;\n"
657 "#endif\n"
658 "\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FragColor = gl_Color;\n"
662 "#ifdef USEDIFFUSE\n"
663 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
664 "#endif\n"
665 "\n"
666 "#ifdef USESPECULAR\n"
667 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
668 "# ifdef USECOLORMAPPING\n"
669 "       gl_FragColor *= tex2;\n"
670 "# endif\n"
671 "# ifdef USEGLOW\n"
672 "       gl_FragColor += tex2;\n"
673 "# endif\n"
674 "# ifdef USEVERTEXTEXTUREBLEND\n"
675 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
676 "# endif\n"
677 "#endif\n"
678 "}\n"
679 "#endif\n"
680 "#else // !MODE_GENERIC\n"
681 "\n"
682 "\n"
683 "\n"
684 "\n"
685 "#ifdef MODE_BLOOMBLUR\n"
686 "varying TexCoord;\n"
687 "#ifdef VERTEX_SHADER\n"
688 "void main(void)\n"
689 "{\n"
690 "       gl_FrontColor = gl_Color;\n"
691 "       TexCoord = gl_MultiTexCoord0.xy;\n"
692 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
693 "}\n"
694 "#endif\n"
695 "\n"
696 "#ifdef FRAGMENT_SHADER\n"
697 "uniform sampler2D Texture_First;\n"
698 "uniform vec4 BloomBlur_Parameters;\n"
699 "\n"
700 "void main(void)\n"
701 "{\n"
702 "       int i;\n"
703 "       vec2 tc = TexCoord;\n"
704 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
705 "       tc += BloomBlur_Parameters.xy;\n"
706 "       for (i = 1;i < SAMPLES;i++)\n"
707 "       {\n"
708 "               color += texture2D(Texture_First, tc).rgb;\n"
709 "               tc += BloomBlur_Parameters.xy;\n"
710 "       }\n"
711 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
712 "}\n"
713 "#endif\n"
714 "#else // !MODE_BLOOMBLUR\n"
715 "#ifdef MODE_REFRACTION\n"
716 "varying vec2 TexCoord;\n"
717 "varying vec4 ModelViewProjectionPosition;\n"
718 "uniform mat4 TexMatrix;\n"
719 "#ifdef VERTEX_SHADER\n"
720 "\n"
721 "void main(void)\n"
722 "{\n"
723 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
724 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
725 "       ModelViewProjectionPosition = gl_Position;\n"
726 "}\n"
727 "#endif\n"
728 "\n"
729 "#ifdef FRAGMENT_SHADER\n"
730 "uniform sampler2D Texture_Normal;\n"
731 "uniform sampler2D Texture_Refraction;\n"
732 "uniform sampler2D Texture_Reflection;\n"
733 "\n"
734 "uniform vec4 DistortScaleRefractReflect;\n"
735 "uniform vec4 ScreenScaleRefractReflect;\n"
736 "uniform vec4 ScreenCenterRefractReflect;\n"
737 "uniform vec4 RefractColor;\n"
738 "uniform vec4 ReflectColor;\n"
739 "uniform float ReflectFactor;\n"
740 "uniform float ReflectOffset;\n"
741 "\n"
742 "void main(void)\n"
743 "{\n"
744 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
745 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
746 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
747 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
748 "       // FIXME temporary hack to detect the case that the reflection\n"
749 "       // gets blackened at edges due to leaving the area that contains actual\n"
750 "       // content.\n"
751 "       // Remove this 'ack once we have a better way to stop this thing from\n"
752 "       // 'appening.\n"
753 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
754 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
755 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
756 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
757 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
758 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
759 "}\n"
760 "#endif\n"
761 "#else // !MODE_REFRACTION\n"
762 "\n"
763 "\n"
764 "\n"
765 "\n"
766 "#ifdef MODE_WATER\n"
767 "varying vec2 TexCoord;\n"
768 "varying vec3 EyeVector;\n"
769 "varying vec4 ModelViewProjectionPosition;\n"
770 "#ifdef VERTEX_SHADER\n"
771 "uniform vec3 EyePosition;\n"
772 "uniform mat4 TexMatrix;\n"
773 "\n"
774 "void main(void)\n"
775 "{\n"
776 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
777 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
778 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
779 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
780 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
781 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
782 "       ModelViewProjectionPosition = gl_Position;\n"
783 "}\n"
784 "#endif\n"
785 "\n"
786 "#ifdef FRAGMENT_SHADER\n"
787 "uniform sampler2D Texture_Normal;\n"
788 "uniform sampler2D Texture_Refraction;\n"
789 "uniform sampler2D Texture_Reflection;\n"
790 "\n"
791 "uniform vec4 DistortScaleRefractReflect;\n"
792 "uniform vec4 ScreenScaleRefractReflect;\n"
793 "uniform vec4 ScreenCenterRefractReflect;\n"
794 "uniform vec4 RefractColor;\n"
795 "uniform vec4 ReflectColor;\n"
796 "uniform float ReflectFactor;\n"
797 "uniform float ReflectOffset;\n"
798 "\n"
799 "void main(void)\n"
800 "{\n"
801 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
802 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
803 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
804 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
805 "       // FIXME temporary hack to detect the case that the reflection\n"
806 "       // gets blackened at edges due to leaving the area that contains actual\n"
807 "       // content.\n"
808 "       // Remove this 'ack once we have a better way to stop this thing from\n"
809 "       // 'appening.\n"
810 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
811 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
812 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
813 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
814 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
815 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
816 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
817 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
818 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
819 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
820 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
821 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
822 "}\n"
823 "#endif\n"
824 "#else // !MODE_WATER\n"
825 "\n"
826 "\n"
827 "\n"
828 "\n"
829 "// common definitions between vertex shader and fragment shader:\n"
830 "\n"
831 "varying vec2 TexCoord;\n"
832 "#ifdef USEVERTEXTEXTUREBLEND\n"
833 "varying vec2 TexCoord2;\n"
834 "#endif\n"
835 "#ifdef USELIGHTMAP\n"
836 "varying vec2 TexCoordLightmap;\n"
837 "#endif\n"
838 "\n"
839 "#ifdef MODE_LIGHTSOURCE\n"
840 "varying vec3 CubeVector;\n"
841 "#endif\n"
842 "\n"
843 "#ifdef MODE_LIGHTSOURCE\n"
844 "varying vec3 LightVector;\n"
845 "#endif\n"
846 "#if defined(MODE_LIGHTDIRECTION)\n"
847 "varying vec3 LightVector;\n"
848 "#endif\n"
849 "\n"
850 "#ifdef USEEYEVECTOR\n"
851 "varying vec3 EyeVector;\n"
852 "#endif\n"
853 "#ifdef USEFOG\n"
854 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
855 "#endif\n"
856 "\n"
857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
858 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
859 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
860 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
861 "#endif\n"
862 "\n"
863 "#ifdef USEREFLECTION\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "#endif\n"
866 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
867 "uniform vec3 LightPosition;\n"
868 "varying vec4 ModelViewPosition;\n"
869 "#endif\n"
870 "\n"
871 "#ifdef MODE_LIGHTSOURCE\n"
872 "uniform vec3 LightPosition;\n"
873 "#endif\n"
874 "uniform vec3 EyePosition;\n"
875 "#ifdef MODE_LIGHTDIRECTION\n"
876 "uniform vec3 LightDir;\n"
877 "#endif\n"
878 "uniform vec4 FogPlane;\n"
879 "\n"
880 "\n"
881 "\n"
882 "\n"
883 "\n"
884 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
885 "\n"
886 "// fragment shader specific:\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "\n"
889 "uniform sampler2D Texture_Normal;\n"
890 "uniform sampler2D Texture_Color;\n"
891 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
892 "uniform sampler2D Texture_Gloss;\n"
893 "//#endif\n"
894 "#ifdef USEGLOW\n"
895 "uniform sampler2D Texture_Glow;\n"
896 "#endif\n"
897 "#ifdef USEVERTEXTEXTUREBLEND\n"
898 "uniform sampler2D Texture_SecondaryNormal;\n"
899 "uniform sampler2D Texture_SecondaryColor;\n"
900 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
901 "uniform sampler2D Texture_SecondaryGloss;\n"
902 "//#endif\n"
903 "#ifdef USEGLOW\n"
904 "uniform sampler2D Texture_SecondaryGlow;\n"
905 "#endif\n"
906 "#endif\n"
907 "#ifdef USECOLORMAPPING\n"
908 "uniform sampler2D Texture_Pants;\n"
909 "uniform sampler2D Texture_Shirt;\n"
910 "#endif\n"
911 "#ifdef USEFOG\n"
912 "uniform sampler2D Texture_FogMask;\n"
913 "#endif\n"
914 "#ifdef USELIGHTMAP\n"
915 "uniform sampler2D Texture_Lightmap;\n"
916 "#endif\n"
917 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
918 "uniform sampler2D Texture_Deluxemap;\n"
919 "#endif\n"
920 "#ifdef USEREFLECTION\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "#endif\n"
923 "\n"
924 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
925 "uniform sampler2DRect Texture_ScreenDepth;\n"
926 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
927 "#endif\n"
928 "#ifdef USEDEFERREDLIGHTMAP\n"
929 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
930 "uniform sampler2DRect Texture_ScreenSpecular;\n"
931 "#endif\n"
932 "\n"
933 "uniform myhalf3 Color_Pants;\n"
934 "uniform myhalf3 Color_Shirt;\n"
935 "uniform myhalf3 FogColor;\n"
936 "\n"
937 "#ifdef USEFOG\n"
938 "uniform float FogRangeRecip;\n"
939 "uniform float FogPlaneViewDist;\n"
940 "uniform float FogHeightFade;\n"
941 "float FogVertex(void)\n"
942 "{\n"
943 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
944 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
945 "       float fogfrac;\n"
946 "#ifdef USEFOGOUTSIDE\n"
947 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
948 "#else\n"
949 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
950 "#endif\n"
951 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
952 "}\n"
953 "#endif\n"
954 "\n"
955 "#ifdef USEOFFSETMAPPING\n"
956 "uniform float OffsetMapping_Scale;\n"
957 "vec2 OffsetMapping(vec2 TexCoord)\n"
958 "{\n"
959 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
960 "       // 14 sample relief mapping: linear search and then binary search\n"
961 "       // this basically steps forward a small amount repeatedly until it finds\n"
962 "       // itself inside solid, then jitters forward and back using decreasing\n"
963 "       // amounts to find the impact\n"
964 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
965 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
966 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
967 "       vec3 RT = vec3(TexCoord, 1);\n"
968 "       OffsetVector *= 0.1;\n"
969 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
970 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
971 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
972 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
973 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
974 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
975 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
976 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
977 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
978 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
979 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
980 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
981 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
982 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
983 "       return RT.xy;\n"
984 "#else\n"
985 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
986 "       // this basically moves forward the full distance, and then backs up based\n"
987 "       // on height of samples\n"
988 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
989 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
990 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
991 "       TexCoord += OffsetVector;\n"
992 "       OffsetVector *= 0.333;\n"
993 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
994 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
995 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
996 "       return TexCoord;\n"
997 "#endif\n"
998 "}\n"
999 "#endif // USEOFFSETMAPPING\n"
1000 "\n"
1001 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1002 "uniform sampler2D Texture_Attenuation;\n"
1003 "uniform samplerCube Texture_Cube;\n"
1004 "\n"
1005 "#ifdef USESHADOWMAPRECT\n"
1006 "# ifdef USESHADOWSAMPLER\n"
1007 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1008 "# else\n"
1009 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1010 "# endif\n"
1011 "#endif\n"
1012 "\n"
1013 "#ifdef USESHADOWMAP2D\n"
1014 "# ifdef USESHADOWSAMPLER\n"
1015 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1016 "# else\n"
1017 "uniform sampler2D Texture_ShadowMap2D;\n"
1018 "# endif\n"
1019 "#endif\n"
1020 "\n"
1021 "#ifdef USESHADOWMAPVSDCT\n"
1022 "uniform samplerCube Texture_CubeProjection;\n"
1023 "#endif\n"
1024 "\n"
1025 "#ifdef USESHADOWMAPCUBE\n"
1026 "# ifdef USESHADOWSAMPLER\n"
1027 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1028 "# else\n"
1029 "uniform samplerCube Texture_ShadowMapCube;\n"
1030 "# endif\n"
1031 "#endif\n"
1032 "\n"
1033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1034 "uniform vec2 ShadowMap_TextureScale;\n"
1035 "uniform vec4 ShadowMap_Parameters;\n"
1036 "#endif\n"
1037 "\n"
1038 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1039 "# ifndef USESHADOWMAPVSDCT\n"
1040 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1041 "{\n"
1042 "       vec3 adir = abs(dir);\n"
1043 "       vec2 tc;\n"
1044 "       vec2 offset;\n"
1045 "       float ma;\n"
1046 "       if (adir.x > adir.y)\n"
1047 "       {\n"
1048 "               if (adir.x > adir.z) // X\n"
1049 "               {\n"
1050 "                       ma = adir.x;\n"
1051 "                       tc = dir.zy;\n"
1052 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1053 "               }\n"
1054 "               else // Z\n"
1055 "               {\n"
1056 "                       ma = adir.z;\n"
1057 "                       tc = dir.xy;\n"
1058 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1059 "               }\n"
1060 "       }\n"
1061 "       else\n"
1062 "       {\n"
1063 "               if (adir.y > adir.z) // Y\n"
1064 "               {\n"
1065 "                       ma = adir.y;\n"
1066 "                       tc = dir.xz;\n"
1067 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1068 "               }\n"
1069 "               else // Z\n"
1070 "               {\n"
1071 "                       ma = adir.z;\n"
1072 "                       tc = dir.xy;\n"
1073 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1074 "               }\n"
1075 "       }\n"
1076 "\n"
1077 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1078 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1079 "       stc.z += ShadowMap_Parameters.z;\n"
1080 "       return stc;\n"
1081 "}\n"
1082 "# else\n"
1083 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1084 "{\n"
1085 "       vec3 adir = abs(dir);\n"
1086 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1087 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1088 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1089 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1090 "       stc.z += ShadowMap_Parameters.z;\n"
1091 "       return stc;\n"
1092 "}\n"
1093 "# endif\n"
1094 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1095 "\n"
1096 "#ifdef USESHADOWMAPCUBE\n"
1097 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1098 "{\n"
1099 "       vec3 adir = abs(dir);\n"
1100 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1101 "}\n"
1102 "#endif\n"
1103 "\n"
1104 "# ifdef USESHADOWMAPRECT\n"
1105 "float ShadowMapCompare(vec3 dir)\n"
1106 "{\n"
1107 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1108 "       float f;\n"
1109 "#  ifdef USESHADOWSAMPLER\n"
1110 "\n"
1111 "#    ifdef USESHADOWMAPPCF\n"
1112 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1113 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1114 "#    else\n"
1115 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1116 "#    endif\n"
1117 "\n"
1118 "#  else\n"
1119 "\n"
1120 "#    ifdef USESHADOWMAPPCF\n"
1121 "#      if USESHADOWMAPPCF > 1\n"
1122 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1123 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1124 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1125 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1126 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1127 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1128 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1129 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1130 "#      else\n"
1131 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1132 "       vec2 offset = fract(shadowmaptc.xy);\n"
1133 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1134 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1135 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1136 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1137 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1138 "#      endif\n"
1139 "#    else\n"
1140 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1141 "#    endif\n"
1142 "\n"
1143 "#  endif\n"
1144 "       return f;\n"
1145 "}\n"
1146 "# endif\n"
1147 "\n"
1148 "# ifdef USESHADOWMAP2D\n"
1149 "float ShadowMapCompare(vec3 dir)\n"
1150 "{\n"
1151 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1152 "       float f;\n"
1153 "\n"
1154 "#  ifdef USESHADOWSAMPLER\n"
1155 "#    ifdef USESHADOWMAPPCF\n"
1156 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1157 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1158 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1159 "#    else\n"
1160 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1161 "#    endif\n"
1162 "#  else\n"
1163 "#    ifdef USESHADOWMAPPCF\n"
1164 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1165 "#      ifdef GL_ARB_texture_gather\n"
1166 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1167 "#      else\n"
1168 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1169 "#      endif\n"
1170 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1171 "       center *= ShadowMap_TextureScale;\n"
1172 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1173 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1174 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1175 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1176 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1177 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1178 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1179 "#     else\n"
1180 "#      ifdef GL_EXT_gpu_shader4\n"
1181 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1182 "#      else\n"
1183 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1184 "#      endif\n"
1185 "#      if USESHADOWMAPPCF > 1\n"
1186 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1187 "       center *= ShadowMap_TextureScale;\n"
1188 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1189 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1190 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1191 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1192 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1193 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1194 "#      else\n"
1195 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1196 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1197 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1198 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1199 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1200 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1201 "#      endif\n"
1202 "#     endif\n"
1203 "#    else\n"
1204 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1205 "#    endif\n"
1206 "#  endif\n"
1207 "       return f;\n"
1208 "}\n"
1209 "# endif\n"
1210 "\n"
1211 "# ifdef USESHADOWMAPCUBE\n"
1212 "float ShadowMapCompare(vec3 dir)\n"
1213 "{\n"
1214 "       // apply depth texture cubemap as light filter\n"
1215 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1216 "       float f;\n"
1217 "#  ifdef USESHADOWSAMPLER\n"
1218 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1219 "#  else\n"
1220 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1221 "#  endif\n"
1222 "       return f;\n"
1223 "}\n"
1224 "# endif\n"
1225 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1226 "#endif // FRAGMENT_SHADER\n"
1227 "\n"
1228 "\n"
1229 "\n"
1230 "\n"
1231 "#ifdef MODE_DEFERREDGEOMETRY\n"
1232 "#ifdef VERTEX_SHADER\n"
1233 "uniform mat4 TexMatrix;\n"
1234 "#ifdef USEVERTEXTEXTUREBLEND\n"
1235 "uniform mat4 BackgroundTexMatrix;\n"
1236 "#endif\n"
1237 "uniform mat4 ModelViewMatrix;\n"
1238 "void main(void)\n"
1239 "{\n"
1240 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1241 "#ifdef USEVERTEXTEXTUREBLEND\n"
1242 "       gl_FrontColor = gl_Color;\n"
1243 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1244 "#endif\n"
1245 "\n"
1246 "       // transform unnormalized eye direction into tangent space\n"
1247 "#ifdef USEOFFSETMAPPING\n"
1248 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1249 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1250 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1251 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1252 "#endif\n"
1253 "\n"
1254 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1255 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1256 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1257 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1258 "}\n"
1259 "#endif // VERTEX_SHADER\n"
1260 "\n"
1261 "#ifdef FRAGMENT_SHADER\n"
1262 "void main(void)\n"
1263 "{\n"
1264 "#ifdef USEOFFSETMAPPING\n"
1265 "       // apply offsetmapping\n"
1266 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1267 "#define TexCoord TexCoordOffset\n"
1268 "#endif\n"
1269 "\n"
1270 "#ifdef USEALPHAKILL\n"
1271 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1272 "               discard;\n"
1273 "#endif\n"
1274 "\n"
1275 "#ifdef USEVERTEXTEXTUREBLEND\n"
1276 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1277 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1278 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1279 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1280 "#endif\n"
1281 "\n"
1282 "#ifdef USEVERTEXTEXTUREBLEND\n"
1283 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1284 "#else\n"
1285 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1286 "#endif\n"
1287 "\n"
1288 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1289 "}\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1292 "\n"
1293 "\n"
1294 "\n"
1295 "\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1299 "void main(void)\n"
1300 "{\n"
1301 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1303 "}\n"
1304 "#endif // VERTEX_SHADER\n"
1305 "\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1315 "#endif\n"
1316 "void main(void)\n"
1317 "{\n"
1318 "       // calculate viewspace pixel position\n"
1319 "       vec3 position;\n"
1320 "       position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1321 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1322 "       // decode viewspace pixel normal\n"
1323 "       myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1324 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1325 "       // surfacenormal = pixel normal in viewspace\n"
1326 "       // LightVector = pixel to light in viewspace\n"
1327 "       // CubeVector = position in lightspace\n"
1328 "       // eyevector = pixel to view in viewspace\n"
1329 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1330 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1331 "#ifdef USEDIFFUSE\n"
1332 "       // calculate diffuse shading\n"
1333 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1334 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1335 "#endif\n"
1336 "#ifdef USESPECULAR\n"
1337 "       // calculate directional shading\n"
1338 "       vec3 eyevector = position * -1.0;\n"
1339 "#  ifdef USEEXACTSPECULARMATH\n"
1340 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1341 "#  else\n"
1342 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1343 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1344 "#  endif\n"
1345 "#endif\n"
1346 "\n"
1347 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1348 "       fade *= ShadowMapCompare(CubeVector);\n"
1349 "#endif\n"
1350 "\n"
1351 "#ifdef USEDIFFUSE\n"
1352 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1353 "#else\n"
1354 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1355 "#endif\n"
1356 "#ifdef USESPECULAR\n"
1357 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1358 "#else\n"
1359 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1360 "#endif\n"
1361 "\n"
1362 "# ifdef USECUBEFILTER\n"
1363 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1364 "       gl_FragData[0] *= cubecolor;\n"
1365 "       gl_FragData[1] *= cubecolor;\n"
1366 "# endif\n"
1367 "}\n"
1368 "#endif // FRAGMENT_SHADER\n"
1369 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1370 "\n"
1371 "\n"
1372 "\n"
1373 "\n"
1374 "#ifdef VERTEX_SHADER\n"
1375 "uniform mat4 TexMatrix;\n"
1376 "#ifdef USEVERTEXTEXTUREBLEND\n"
1377 "uniform mat4 BackgroundTexMatrix;\n"
1378 "#endif\n"
1379 "#ifdef MODE_LIGHTSOURCE\n"
1380 "uniform mat4 ModelToLight;\n"
1381 "#endif\n"
1382 "void main(void)\n"
1383 "{\n"
1384 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1385 "       gl_FrontColor = gl_Color;\n"
1386 "#endif\n"
1387 "       // copy the surface texcoord\n"
1388 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1391 "#endif\n"
1392 "#ifdef USELIGHTMAP\n"
1393 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1394 "#endif\n"
1395 "\n"
1396 "#ifdef MODE_LIGHTSOURCE\n"
1397 "       // transform vertex position into light attenuation/cubemap space\n"
1398 "       // (-1 to +1 across the light box)\n"
1399 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1400 "\n"
1401 "# ifdef USEDIFFUSE\n"
1402 "       // transform unnormalized light direction into tangent space\n"
1403 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1404 "       //  normalize it per pixel)\n"
1405 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1406 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1407 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1408 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1409 "# endif\n"
1410 "#endif\n"
1411 "\n"
1412 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1413 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1414 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1415 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1416 "#endif\n"
1417 "\n"
1418 "       // transform unnormalized eye direction into tangent space\n"
1419 "#ifdef USEEYEVECTOR\n"
1420 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1421 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1422 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1423 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1424 "#endif\n"
1425 "\n"
1426 "#ifdef USEFOG\n"
1427 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1428 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1429 "#endif\n"
1430 "\n"
1431 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1432 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1433 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1434 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1435 "#endif\n"
1436 "\n"
1437 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1438 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1439 "\n"
1440 "#ifdef USEREFLECTION\n"
1441 "       ModelViewProjectionPosition = gl_Position;\n"
1442 "#endif\n"
1443 "}\n"
1444 "#endif // VERTEX_SHADER\n"
1445 "\n"
1446 "\n"
1447 "\n"
1448 "\n"
1449 "#ifdef FRAGMENT_SHADER\n"
1450 "#ifdef USEDEFERREDLIGHTMAP\n"
1451 "uniform myhalf3 DeferredMod_Diffuse;\n"
1452 "uniform myhalf3 DeferredMod_Specular;\n"
1453 "#endif\n"
1454 "uniform myhalf3 Color_Ambient;\n"
1455 "uniform myhalf3 Color_Diffuse;\n"
1456 "uniform myhalf3 Color_Specular;\n"
1457 "uniform myhalf SpecularPower;\n"
1458 "#ifdef USEGLOW\n"
1459 "uniform myhalf3 Color_Glow;\n"
1460 "#endif\n"
1461 "uniform myhalf Alpha;\n"
1462 "#ifdef USEREFLECTION\n"
1463 "uniform vec4 DistortScaleRefractReflect;\n"
1464 "uniform vec4 ScreenScaleRefractReflect;\n"
1465 "uniform vec4 ScreenCenterRefractReflect;\n"
1466 "uniform myhalf4 ReflectColor;\n"
1467 "#endif\n"
1468 "#ifdef MODE_LIGHTDIRECTION\n"
1469 "uniform myhalf3 LightColor;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTSOURCE\n"
1472 "uniform myhalf3 LightColor;\n"
1473 "#endif\n"
1474 "void main(void)\n"
1475 "{\n"
1476 "#ifdef USEOFFSETMAPPING\n"
1477 "       // apply offsetmapping\n"
1478 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1479 "#define TexCoord TexCoordOffset\n"
1480 "#endif\n"
1481 "\n"
1482 "       // combine the diffuse textures (base, pants, shirt)\n"
1483 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1484 "#ifdef USEALPHAKILL\n"
1485 "       if (color.a < 0.5)\n"
1486 "               discard;\n"
1487 "#endif\n"
1488 "       color.a *= Alpha;\n"
1489 "#ifdef USECOLORMAPPING\n"
1490 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1491 "#endif\n"
1492 "#ifdef USEVERTEXTEXTUREBLEND\n"
1493 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1494 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1495 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1496 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1497 "       color.a = 1.0;\n"
1498 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1499 "#endif\n"
1500 "\n"
1501 "       // get the surface normal\n"
1502 "#ifdef USEVERTEXTEXTUREBLEND\n"
1503 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1504 "#else\n"
1505 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1506 "#endif\n"
1507 "\n"
1508 "       // get the material colors\n"
1509 "       myhalf3 diffusetex = color.rgb;\n"
1510 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1511 "# ifdef USEVERTEXTEXTUREBLEND\n"
1512 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1513 "# else\n"
1514 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1515 "# endif\n"
1516 "#endif\n"
1517 "\n"
1518 "\n"
1519 "\n"
1520 "\n"
1521 "#ifdef MODE_LIGHTSOURCE\n"
1522 "       // light source\n"
1523 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1524 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1525 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1526 "#ifdef USESPECULAR\n"
1527 "#ifdef USEEXACTSPECULARMATH\n"
1528 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1529 "#else\n"
1530 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1531 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1532 "#endif\n"
1533 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1534 "#endif\n"
1535 "       color.rgb *= LightColor;\n"
1536 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1537 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1538 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1539 "#endif\n"
1540 "# ifdef USECUBEFILTER\n"
1541 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1542 "# endif\n"
1543 "#endif // MODE_LIGHTSOURCE\n"
1544 "\n"
1545 "\n"
1546 "\n"
1547 "\n"
1548 "#ifdef MODE_LIGHTDIRECTION\n"
1549 "#define SHADING\n"
1550 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1551 "#define lightcolor LightColor\n"
1552 "#endif // MODE_LIGHTDIRECTION\n"
1553 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1554 "#define SHADING\n"
1555 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1556 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1557 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1558 "       // convert modelspace light vector to tangentspace\n"
1559 "       myhalf3 lightnormal;\n"
1560 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1561 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1562 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1563 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1564 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1565 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1566 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1567 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1568 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1569 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1570 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1571 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1572 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1573 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1574 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1575 "#define SHADING\n"
1576 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1577 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1578 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1579 "#endif\n"
1580 "\n"
1581 "\n"
1582 "\n"
1583 "\n"
1584 "#ifdef MODE_LIGHTMAP\n"
1585 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1586 "#endif // MODE_LIGHTMAP\n"
1587 "#ifdef MODE_VERTEXCOLOR\n"
1588 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1589 "#endif // MODE_VERTEXCOLOR\n"
1590 "#ifdef MODE_FLATCOLOR\n"
1591 "       color.rgb = diffusetex * Color_Ambient;\n"
1592 "#endif // MODE_FLATCOLOR\n"
1593 "\n"
1594 "\n"
1595 "\n"
1596 "\n"
1597 "#ifdef SHADING\n"
1598 "# ifdef USEDIFFUSE\n"
1599 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1600 "#  ifdef USESPECULAR\n"
1601 "#   ifdef USEEXACTSPECULARMATH\n"
1602 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1603 "#   else\n"
1604 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1605 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1606 "#   endif\n"
1607 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1608 "#  else\n"
1609 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1610 "#  endif\n"
1611 "# else\n"
1612 "       color.rgb = diffusetex * Color_Ambient;\n"
1613 "# endif\n"
1614 "#endif\n"
1615 "\n"
1616 "#ifdef USEDEFERREDLIGHTMAP\n"
1617 "       color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1618 "       color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1619 "#endif\n"
1620 "\n"
1621 "#ifdef USEGLOW\n"
1622 "#ifdef USEVERTEXTEXTUREBLEND\n"
1623 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1624 "#else\n"
1625 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1626 "#endif\n"
1627 "#endif\n"
1628 "\n"
1629 "#ifdef USEFOG\n"
1630 "#ifdef MODE_LIGHTSOURCE\n"
1631 "       color.rgb *= myhalf(FogVertex());\n"
1632 "#else\n"
1633 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1634 "#endif\n"
1635 "#endif\n"
1636 "\n"
1637 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1638 "#ifdef USEREFLECTION\n"
1639 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1640 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1641 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1642 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1643 "       // FIXME temporary hack to detect the case that the reflection\n"
1644 "       // gets blackened at edges due to leaving the area that contains actual\n"
1645 "       // content.\n"
1646 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1647 "       // 'appening.\n"
1648 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1649 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1650 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1651 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1652 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1653 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1654 "#endif\n"
1655 "\n"
1656 "       gl_FragColor = vec4(color);\n"
1657 "}\n"
1658 "#endif // FRAGMENT_SHADER\n"
1659 "\n"
1660 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1661 "#endif // !MODE_DEFERREDGEOMETRY\n"
1662 "#endif // !MODE_WATER\n"
1663 "#endif // !MODE_REFRACTION\n"
1664 "#endif // !MODE_BLOOMBLUR\n"
1665 "#endif // !MODE_GENERIC\n"
1666 "#endif // !MODE_POSTPROCESS\n"
1667 "#endif // !MODE_SHOWDEPTH\n"
1668 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1669 ;
1670
1671 /*
1672 =========================================================================================================================================================
1673
1674
1675
1676 =========================================================================================================================================================
1677
1678
1679
1680 =========================================================================================================================================================
1681
1682
1683
1684 =========================================================================================================================================================
1685
1686
1687
1688 =========================================================================================================================================================
1689
1690
1691
1692 =========================================================================================================================================================
1693
1694
1695
1696 =========================================================================================================================================================
1697 */
1698
1699 const char *builtincgshaderstring =
1700 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1701 "// written by Forest 'LordHavoc' Hale\n"
1702 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1703 "\n"
1704 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1705 "# define USEFOG\n"
1706 "#endif\n"
1707 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1708 "#define USELIGHTMAP\n"
1709 "#endif\n"
1710 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1711 "#define USEEYEVECTOR\n"
1712 "#endif\n"
1713 "\n"
1714 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1715 "#ifdef VERTEX_SHADER\n"
1716 "void main\n"
1717 "(\n"
1718 "float4 gl_Vertex : POSITION,\n"
1719 "uniform float4x4 ModelViewProjectionMatrix,\n"
1720 "out float4 gl_Position : POSITION\n"
1721 ")\n"
1722 "{\n"
1723 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1724 "}\n"
1725 "#endif\n"
1726 "#else // !MODE_DEPTH_ORSHADOW\n"
1727 "\n"
1728 "\n"
1729 "\n"
1730 "\n"
1731 "#ifdef MODE_SHOWDEPTH\n"
1732 "#ifdef VERTEX_SHADER\n"
1733 "void main\n"
1734 "(\n"
1735 "float4 gl_Vertex : POSITION,\n"
1736 "uniform float4x4 ModelViewProjectionMatrix,\n"
1737 "out float4 gl_Position : POSITION,\n"
1738 "out float4 gl_FrontColor : COLOR0\n"
1739 ")\n"
1740 "{\n"
1741 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1742 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1743 "}\n"
1744 "#endif\n"
1745 "\n"
1746 "#ifdef FRAGMENT_SHADER\n"
1747 "void main\n"
1748 "(\n"
1749 "float4 gl_FrontColor : COLOR0,\n"
1750 "out float4 gl_FragColor : COLOR\n"
1751 ")\n"
1752 "{\n"
1753 "       gl_FragColor = gl_FrontColor;\n"
1754 "}\n"
1755 "#endif\n"
1756 "#else // !MODE_SHOWDEPTH\n"
1757 "\n"
1758 "\n"
1759 "\n"
1760 "\n"
1761 "#ifdef MODE_POSTPROCESS\n"
1762 "\n"
1763 "#ifdef VERTEX_SHADER\n"
1764 "void main\n"
1765 "(\n"
1766 "float4 gl_Vertex : POSITION,\n"
1767 "uniform float4x4 ModelViewProjectionMatrix,\n"
1768 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1769 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1770 "out float4 gl_Position : POSITION,\n"
1771 "out float2 TexCoord1 : TEXCOORD0,\n"
1772 "out float2 TexCoord2 : TEXCOORD1\n"
1773 ")\n"
1774 "{\n"
1775 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1776 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1777 "#ifdef USEBLOOM\n"
1778 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1779 "#endif\n"
1780 "}\n"
1781 "#endif\n"
1782 "\n"
1783 "#ifdef FRAGMENT_SHADER\n"
1784 "void main\n"
1785 "(\n"
1786 "float2 TexCoord1 : TEXCOORD0,\n"
1787 "float2 TexCoord2 : TEXCOORD1,\n"
1788 "uniform sampler2D Texture_First,\n"
1789 "#ifdef USEBLOOM\n"
1790 "uniform sampler2D Texture_Second,\n"
1791 "#endif\n"
1792 "#ifdef USEGAMMARAMPS\n"
1793 "uniform sampler2D Texture_GammaRamps,\n"
1794 "#endif\n"
1795 "#ifdef USESATURATION\n"
1796 "uniform float Saturation,\n"
1797 "#endif\n"
1798 "#ifdef USEVIEWTINT\n"
1799 "uniform float4 ViewTintColor,\n"
1800 "#endif\n"
1801 "uniform float4 UserVec1,\n"
1802 "uniform float4 UserVec2,\n"
1803 "uniform float4 UserVec3,\n"
1804 "uniform float4 UserVec4,\n"
1805 "uniform float ClientTime,\n"
1806 "uniform float2 PixelSize,\n"
1807 "out float4 gl_FragColor : COLOR\n"
1808 ")\n"
1809 "{\n"
1810 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1811 "#ifdef USEBLOOM\n"
1812 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1813 "#endif\n"
1814 "#ifdef USEVIEWTINT\n"
1815 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1816 "#endif\n"
1817 "\n"
1818 "#ifdef USEPOSTPROCESSING\n"
1819 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1820 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1821 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1822 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1823 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1824 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1825 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1826 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1827 "#endif\n"
1828 "\n"
1829 "#ifdef USESATURATION\n"
1830 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1831 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1832 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1833 "       gl_FragColor.rgb = mix(float3(y), gl_FragColor.rgb, Saturation);\n"
1834 "#endif\n"
1835 "\n"
1836 "#ifdef USEGAMMARAMPS\n"
1837 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1838 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1839 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1840 "#endif\n"
1841 "}\n"
1842 "#endif\n"
1843 "#else // !MODE_POSTPROCESS\n"
1844 "\n"
1845 "\n"
1846 "\n"
1847 "\n"
1848 "#ifdef MODE_GENERIC\n"
1849 "#ifdef VERTEX_SHADER\n"
1850 "void main\n"
1851 "(\n"
1852 "float4 gl_Vertex : POSITION,\n"
1853 "uniform float4x4 ModelViewProjectionMatrix,\n"
1854 "float4 gl_Color : COLOR0,\n"
1855 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1856 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1857 "out float4 gl_Position : POSITION,\n"
1858 "out float4 gl_FrontColor : COLOR,\n"
1859 "out float2 TexCoord1 : TEXCOORD0,\n"
1860 "out float2 TexCoord2 : TEXCOORD1\n"
1861 ")\n"
1862 "{\n"
1863 "       gl_FrontColor = gl_Color;\n"
1864 "#ifdef USEDIFFUSE\n"
1865 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1866 "#endif\n"
1867 "#ifdef USESPECULAR\n"
1868 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1869 "#endif\n"
1870 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1871 "}\n"
1872 "#endif\n"
1873 "\n"
1874 "#ifdef FRAGMENT_SHADER\n"
1875 "\n"
1876 "void main\n"
1877 "(\n"
1878 "float4 gl_FrontColor : COLOR,\n"
1879 "float2 TexCoord1 : TEXCOORD0,\n"
1880 "float2 TexCoord2 : TEXCOORD1,\n"
1881 "#ifdef USEDIFFUSE\n"
1882 "uniform sampler2D Texture_First,\n"
1883 "#endif\n"
1884 "#ifdef USESPECULAR\n"
1885 "uniform sampler2D Texture_Second,\n"
1886 "#endif\n"
1887 "out float4 gl_FragColor : COLOR\n"
1888 ")\n"
1889 "{\n"
1890 "       gl_FragColor = gl_FrontColor;\n"
1891 "#ifdef USEDIFFUSE\n"
1892 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1893 "#endif\n"
1894 "\n"
1895 "#ifdef USESPECULAR\n"
1896 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1897 "# ifdef USECOLORMAPPING\n"
1898 "       gl_FragColor *= tex2;\n"
1899 "# endif\n"
1900 "# ifdef USEGLOW\n"
1901 "       gl_FragColor += tex2;\n"
1902 "# endif\n"
1903 "# ifdef USEVERTEXTEXTUREBLEND\n"
1904 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
1905 "# endif\n"
1906 "#endif\n"
1907 "}\n"
1908 "#endif\n"
1909 "#else // !MODE_GENERIC\n"
1910 "\n"
1911 "\n"
1912 "\n"
1913 "\n"
1914 "#ifdef MODE_BLOOMBLUR\n"
1915 "#ifdef VERTEX_SHADER\n"
1916 "void main\n"
1917 "(\n"
1918 "float4 gl_Vertex : POSITION,\n"
1919 "uniform float4x4 ModelViewProjectionMatrix,\n"
1920 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1921 "out float4 gl_Position : POSITION,\n"
1922 "out float2 TexCoord : TEXCOORD0\n"
1923 ")\n"
1924 "{\n"
1925 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1926 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1927 "}\n"
1928 "#endif\n"
1929 "\n"
1930 "#ifdef FRAGMENT_SHADER\n"
1931 "\n"
1932 "void main\n"
1933 "(\n"
1934 "float2 TexCoord : TEXCOORD0,\n"
1935 "uniform sampler2D Texture_First,\n"
1936 "uniform float4 BloomBlur_Parameters,\n"
1937 "out float4 gl_FragColor : COLOR\n"
1938 ")\n"
1939 "{\n"
1940 "       int i;\n"
1941 "       float2 tc = TexCoord;\n"
1942 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1943 "       tc += BloomBlur_Parameters.xy;\n"
1944 "       for (i = 1;i < SAMPLES;i++)\n"
1945 "       {\n"
1946 "               color += tex2D(Texture_First, tc).rgb;\n"
1947 "               tc += BloomBlur_Parameters.xy;\n"
1948 "       }\n"
1949 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1950 "}\n"
1951 "#endif\n"
1952 "#else // !MODE_BLOOMBLUR\n"
1953 "#ifdef MODE_REFRACTION\n"
1954 "#ifdef VERTEX_SHADER\n"
1955 "void main\n"
1956 "(\n"
1957 "float4 gl_Vertex : POSITION,\n"
1958 "uniform float4x4 ModelViewProjectionMatrix,\n"
1959 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1960 "uniform mat4 TexMatrix,\n"
1961 "uniform float3 EyePosition,\n"
1962 "out float4 gl_Position : POSITION,\n"
1963 "out float2 TexCoord : TEXCOORD0,\n"
1964 "out float3 EyeVector : TEXCOORD1,\n"
1965 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1966 ")\n"
1967 "{\n"
1968 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1969 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1970 "       ModelViewProjectionPosition = gl_Position;\n"
1971 "}\n"
1972 "#endif\n"
1973 "\n"
1974 "#ifdef FRAGMENT_SHADER\n"
1975 "void main\n"
1976 "(\n"
1977 "float2 TexCoord : TEXCOORD0,\n"
1978 "float3 EyeVector : TEXCOORD1,\n"
1979 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1980 "uniform sampler2D Texture_Normal,\n"
1981 "uniform sampler2D Texture_Refraction,\n"
1982 "uniform sampler2D Texture_Reflection,\n"
1983 "uniform float4 DistortScaleRefractReflect,\n"
1984 "uniform float4 ScreenScaleRefractReflect,\n"
1985 "uniform float4 ScreenCenterRefractReflect,\n"
1986 "uniform float4 RefractColor,\n"
1987 "out float4 gl_FragColor : COLOR\n"
1988 ")\n"
1989 "{\n"
1990 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1991 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1992 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1993 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1994 "       // FIXME temporary hack to detect the case that the reflection\n"
1995 "       // gets blackened at edges due to leaving the area that contains actual\n"
1996 "       // content.\n"
1997 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1998 "       // 'appening.\n"
1999 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2000 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2001 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2002 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2003 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2004 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2005 "}\n"
2006 "#endif\n"
2007 "#else // !MODE_REFRACTION\n"
2008 "\n"
2009 "\n"
2010 "\n"
2011 "\n"
2012 "#ifdef MODE_WATER\n"
2013 "#ifdef VERTEX_SHADER\n"
2014 "\n"
2015 "void main\n"
2016 "(\n"
2017 "float4 gl_Vertex : POSITION,\n"
2018 "uniform float4x4 ModelViewProjectionMatrix,\n"
2019 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2020 "uniform mat4 TexMatrix,\n"
2021 "uniform float3 EyePosition,\n"
2022 "out float4 gl_Position : POSITION,\n"
2023 "out float2 TexCoord : TEXCOORD0,\n"
2024 "out float3 EyeVector : TEXCOORD1,\n"
2025 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2026 ")\n"
2027 "{\n"
2028 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2029 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2030 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2031 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2032 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2033 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2034 "       ModelViewProjectionPosition = gl_Position;\n"
2035 "}\n"
2036 "#endif\n"
2037 "\n"
2038 "#ifdef FRAGMENT_SHADER\n"
2039 "void main\n"
2040 "(\n"
2041 "float2 TexCoord : TEXCOORD0,\n"
2042 "float3 EyeVector : TEXCOORD1,\n"
2043 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2044 "uniform sampler2D Texture_Normal,\n"
2045 "uniform sampler2D Texture_Refraction,\n"
2046 "uniform sampler2D Texture_Reflection,\n"
2047 "uniform float4 DistortScaleRefractReflect,\n"
2048 "uniform float4 ScreenScaleRefractReflect,\n"
2049 "uniform float4 ScreenCenterRefractReflect,\n"
2050 "uniform float4 RefractColor,\n"
2051 "uniform float4 ReflectColor,\n"
2052 "uniform float ReflectFactor,\n"
2053 "uniform float ReflectOffset,\n"
2054 "out float4 gl_FragColor : COLOR\n"
2055 ")\n"
2056 "{\n"
2057 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2058 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2059 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2060 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2061 "       // FIXME temporary hack to detect the case that the reflection\n"
2062 "       // gets blackened at edges due to leaving the area that contains actual\n"
2063 "       // content.\n"
2064 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2065 "       // 'appening.\n"
2066 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2067 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2068 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2069 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2070 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2071 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2072 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2073 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2074 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2075 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2076 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2077 "       gl_FragColor = mix(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2078 "}\n"
2079 "#endif\n"
2080 "#else // !MODE_WATER\n"
2081 "\n"
2082 "\n"
2083 "\n"
2084 "\n"
2085 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2086 "\n"
2087 "// fragment shader specific:\n"
2088 "#ifdef FRAGMENT_SHADER\n"
2089 "\n"
2090 "#ifdef USEFOG\n"
2091 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2092 "{\n"
2093 "       float fogfrac;\n"
2094 "#ifdef USEFOGOUTSIDE\n"
2095 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2096 "#else\n"
2097 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2098 "#endif\n"
2099 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2100 "}\n"
2101 "#endif\n"
2102 "\n"
2103 "#ifdef USEOFFSETMAPPING\n"
2104 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2105 "{\n"
2106 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2107 "       // 14 sample relief mapping: linear search and then binary search\n"
2108 "       // this basically steps forward a small amount repeatedly until it finds\n"
2109 "       // itself inside solid, then jitters forward and back using decreasing\n"
2110 "       // amounts to find the impact\n"
2111 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2112 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2113 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2114 "       float3 RT = float3(TexCoord, 1);\n"
2115 "       OffsetVector *= 0.1;\n"
2116 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2117 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2118 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2119 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2120 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2121 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2122 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2123 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2124 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2125 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2126 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2127 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2128 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2129 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2130 "       return RT.xy;\n"
2131 "#else\n"
2132 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2133 "       // this basically moves forward the full distance, and then backs up based\n"
2134 "       // on height of samples\n"
2135 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2136 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2137 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2138 "       TexCoord += OffsetVector;\n"
2139 "       OffsetVector *= 0.333;\n"
2140 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2141 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2142 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2143 "       return TexCoord;\n"
2144 "#endif\n"
2145 "}\n"
2146 "#endif // USEOFFSETMAPPING\n"
2147 "\n"
2148 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2149 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2150 "# ifndef USESHADOWMAPVSDCT\n"
2151 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2152 "{\n"
2153 "       float3 adir = abs(dir);\n"
2154 "       float2 tc;\n"
2155 "       float2 offset;\n"
2156 "       float ma;\n"
2157 "       if (adir.x > adir.y)\n"
2158 "       {\n"
2159 "               if (adir.x > adir.z) // X\n"
2160 "               {\n"
2161 "                       ma = adir.x;\n"
2162 "                       tc = dir.zy;\n"
2163 "                       offset = float2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2164 "               }\n"
2165 "               else // Z\n"
2166 "               {\n"
2167 "                       ma = adir.z;\n"
2168 "                       tc = dir.xy;\n"
2169 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2170 "               }\n"
2171 "       }\n"
2172 "       else\n"
2173 "       {\n"
2174 "               if (adir.y > adir.z) // Y\n"
2175 "               {\n"
2176 "                       ma = adir.y;\n"
2177 "                       tc = dir.xz;\n"
2178 "                       offset = float2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2179 "               }\n"
2180 "               else // Z\n"
2181 "               {\n"
2182 "                       ma = adir.z;\n"
2183 "                       tc = dir.xy;\n"
2184 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2185 "               }\n"
2186 "       }\n"
2187 "\n"
2188 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2189 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2190 "       stc.z += ShadowMap_Parameters.z;\n"
2191 "       return stc;\n"
2192 "}\n"
2193 "# else\n"
2194 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2195 "{\n"
2196 "       float3 adir = abs(dir);\n"
2197 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2198 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2199 "       float3 stc = float3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2200 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2201 "       stc.z += ShadowMap_Parameters.z;\n"
2202 "       return stc;\n"
2203 "}\n"
2204 "# endif\n"
2205 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2206 "\n"
2207 "#ifdef USESHADOWMAPCUBE\n"
2208 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2209 "{\n"
2210 "    float3 adir = abs(dir);\n"
2211 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2212 "}\n"
2213 "#endif\n"
2214 "\n"
2215 "# ifdef USESHADOWMAPRECT\n"
2216 "#ifdef USESHADOWMAPVSDCT\n"
2217 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2218 "#else\n"
2219 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2220 "#endif\n"
2221 "{\n"
2222 "#ifdef USESHADOWMAPVSDCT\n"
2223 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2224 "#else\n"
2225 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2226 "#endif\n"
2227 "       float f;\n"
2228 "#  ifdef USESHADOWSAMPLER\n"
2229 "\n"
2230 "#    ifdef USESHADOWMAPPCF\n"
2231 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2232 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2233 "#    else\n"
2234 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2235 "#    endif\n"
2236 "\n"
2237 "#  else\n"
2238 "\n"
2239 "#    ifdef USESHADOWMAPPCF\n"
2240 "#      if USESHADOWMAPPCF > 1\n"
2241 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2242 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2243 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2244 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2245 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2246 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2247 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2248 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2249 "#      else\n"
2250 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2251 "    float2 offset = fract(shadowmaptc.xy);\n"
2252 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2253 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2254 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2255 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2256 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2257 "#      endif\n"
2258 "#    else\n"
2259 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2260 "#    endif\n"
2261 "\n"
2262 "#  endif\n"
2263 "       return f;\n"
2264 "}\n"
2265 "# endif\n"
2266 "\n"
2267 "# ifdef USESHADOWMAP2D\n"
2268 "#ifdef USESHADOWMAPVSDCT\n"
2269 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2270 "#else\n"
2271 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2272 "#endif\n"
2273 "{\n"
2274 "#ifdef USESHADOWMAPVSDCT\n"
2275 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2276 "#else\n"
2277 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2278 "#endif\n"
2279 "    float f;\n"
2280 "\n"
2281 "#  ifdef USESHADOWSAMPLER\n"
2282 "#    ifdef USESHADOWMAPPCF\n"
2283 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2284 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2285 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2286 "#    else\n"
2287 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2288 "#    endif\n"
2289 "#  else\n"
2290 "#    ifdef USESHADOWMAPPCF\n"
2291 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2292 "#      ifdef GL_ARB_texture_gather\n"
2293 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2294 "#      else\n"
2295 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2296 "#      endif\n"
2297 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2298 "    center *= ShadowMap_TextureScale;\n"
2299 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2300 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2301 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2302 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2303 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2304 "                mix(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2305 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2306 "#     else\n"
2307 "#      ifdef GL_EXT_gpu_shader4\n"
2308 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, ifloat2(x, y)).r\n"
2309 "#      else\n"
2310 "#        define texval(x, y) tex2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2311 "#      endif\n"
2312 "#      if USESHADOWMAPPCF > 1\n"
2313 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2314 "    center *= ShadowMap_TextureScale;\n"
2315 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2316 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2317 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2318 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2319 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2320 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2321 "#      else\n"
2322 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
2323 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2324 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2325 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2326 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2327 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2328 "#      endif\n"
2329 "#     endif\n"
2330 "#    else\n"
2331 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2332 "#    endif\n"
2333 "#  endif\n"
2334 "    return f;\n"
2335 "}\n"
2336 "# endif\n"
2337 "\n"
2338 "# ifdef USESHADOWMAPCUBE\n"
2339 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2340 "{\n"
2341 "    // apply depth texture cubemap as light filter\n"
2342 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2343 "    float f;\n"
2344 "#  ifdef USESHADOWSAMPLER\n"
2345 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2346 "#  else\n"
2347 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2348 "#  endif\n"
2349 "    return f;\n"
2350 "}\n"
2351 "# endif\n"
2352 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2353 "#endif // FRAGMENT_SHADER\n"
2354 "\n"
2355 "\n"
2356 "\n"
2357 "\n"
2358 "#ifdef MODE_DEFERREDGEOMETRY\n"
2359 "#ifdef VERTEX_SHADER\n"
2360 "void main\n"
2361 "(\n"
2362 "float4 gl_Vertex : POSITION,\n"
2363 "uniform float4x4 ModelViewProjectionMatrix,\n"
2364 "#ifdef USEVERTEXTEXTUREBLEND\n"
2365 "float4 gl_Color : COLOR0,\n"
2366 "#endif\n"
2367 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2368 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2369 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2370 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2371 "uniform mat4 TexMatrix,\n"
2372 "#ifdef USEVERTEXTEXTUREBLEND\n"
2373 "uniform mat4 BackgroundTexMatrix,\n"
2374 "#endif\n"
2375 "uniform mat4 ModelViewMatrix,\n"
2376 "out float4 gl_Position : POSITION,\n"
2377 "out float4 gl_FrontColor : COLOR,\n"
2378 "out float4 TexCoordBoth : TEXCOORD0,\n"
2379 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2380 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2381 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2382 ")\n"
2383 "{\n"
2384 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2385 "#ifdef USEVERTEXTEXTUREBLEND\n"
2386 "       gl_FrontColor = gl_Color;\n"
2387 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2388 "#endif\n"
2389 "\n"
2390 "       // transform unnormalized eye direction into tangent space\n"
2391 "#ifdef USEOFFSETMAPPING\n"
2392 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2393 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2394 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2395 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2396 "#endif\n"
2397 "\n"
2398 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2399 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2400 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2401 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2402 "}\n"
2403 "#endif // VERTEX_SHADER\n"
2404 "\n"
2405 "#ifdef FRAGMENT_SHADER\n"
2406 "void main\n"
2407 "(\n"
2408 "float4 TexCoordBoth : TEXCOORD0,\n"
2409 "float3 EyeVector : TEXCOORD2,\n"
2410 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2411 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2412 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2413 "uniform sampler2D Texture_Normal,\n"
2414 "#ifdef USEALPHAKILL\n"
2415 "uniform sampler2D Texture_Color,\n"
2416 "#endif\n"
2417 "#ifdef USEVERTEXTEXTUREBLEND\n"
2418 "uniform sampler2D Texture_SecondaryNormal,\n"
2419 "#endif\n"
2420 "#ifdef USEOFFSETMAPPING\n"
2421 "uniform float OffsetMapping_Scale,\n"
2422 "#endif\n"
2423 "uniform half SpecularPower,\n"
2424 "out float4 gl_FragColor : COLOR\n"
2425 ")\n"
2426 "{\n"
2427 "       float2 TexCoord = TexCoordBoth.xy;\n"
2428 "#ifdef USEOFFSETMAPPING\n"
2429 "       // apply offsetmapping\n"
2430 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2431 "#define TexCoord TexCoordOffset\n"
2432 "#endif\n"
2433 "\n"
2434 "#ifdef USEALPHAKILL\n"
2435 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2436 "               discard;\n"
2437 "#endif\n"
2438 "\n"
2439 "#ifdef USEVERTEXTEXTUREBLEND\n"
2440 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2441 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2442 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2443 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2444 "#endif\n"
2445 "\n"
2446 "#ifdef USEVERTEXTEXTUREBLEND\n"
2447 "       float3 surfacenormal = mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2448 "#else\n"
2449 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2450 "#endif\n"
2451 "\n"
2452 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2453 "}\n"
2454 "#endif // FRAGMENT_SHADER\n"
2455 "#else // !MODE_DEFERREDGEOMETRY\n"
2456 "\n"
2457 "\n"
2458 "\n"
2459 "\n"
2460 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2461 "#ifdef VERTEX_SHADER\n"
2462 "void main\n"
2463 "(\n"
2464 "float4 gl_Vertex : POSITION,\n"
2465 "uniform float4x4 ModelViewProjectionMatrix,\n"
2466 "uniform mat4 ModelViewMatrix,\n"
2467 "out float4 gl_Position : POSITION,\n"
2468 "out float4 ModelViewPosition : TEXCOORD0\n"
2469 ")\n"
2470 "{\n"
2471 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2472 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2473 "}\n"
2474 "#endif // VERTEX_SHADER\n"
2475 "\n"
2476 "#ifdef FRAGMENT_SHADER\n"
2477 "void main\n"
2478 "(\n"
2479 "float2 Pixel : WPOS,\n"
2480 "float4 ModelViewPosition : TEXCOORD0,\n"
2481 "uniform mat4 ViewToLight,\n"
2482 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2483 "uniform float3 LightPosition,\n"
2484 "uniform half3 DeferredColor_Ambient,\n"
2485 "uniform half3 DeferredColor_Diffuse,\n"
2486 "#ifdef USESPECULAR\n"
2487 "uniform half3 DeferredColor_Specular,\n"
2488 "uniform half SpecularPower,\n"
2489 "#endif\n"
2490 "uniform sampler2D Texture_Attenuation,\n"
2491 "uniform samplerRECT Texture_ScreenDepth,\n"
2492 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2493 "\n"
2494 "#ifdef USESHADOWMAPRECT\n"
2495 "# ifdef USESHADOWSAMPLER\n"
2496 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2497 "# else\n"
2498 "uniform samplerRECT Texture_ShadowMapRect,\n"
2499 "# endif\n"
2500 "#endif\n"
2501 "\n"
2502 "#ifdef USESHADOWMAP2D\n"
2503 "# ifdef USESHADOWSAMPLER\n"
2504 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2505 "# else\n"
2506 "uniform sampler2D Texture_ShadowMap2D,\n"
2507 "# endif\n"
2508 "#endif\n"
2509 "\n"
2510 "#ifdef USESHADOWMAPVSDCT\n"
2511 "uniform samplerCUBE Texture_CubeProjection,\n"
2512 "#endif\n"
2513 "\n"
2514 "#ifdef USESHADOWMAPCUBE\n"
2515 "# ifdef USESHADOWSAMPLER\n"
2516 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2517 "# else\n"
2518 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2519 "# endif\n"
2520 "#endif\n"
2521 "\n"
2522 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2523 "uniform float2 ShadowMap_TextureScale,\n"
2524 "uniform float4 ShadowMap_Parameters,\n"
2525 "#endif\n"
2526 "\n"
2527 "out float4 gl_FragData0 : COLOR0,\n"
2528 "out float4 gl_FragData1 : COLOR1\n"
2529 ")\n"
2530 "{\n"
2531 "       // calculate viewspace pixel position\n"
2532 "       float3 position;\n"
2533 "       position.z = ScreenToDepth.y / (texRECT(Texture_ScreenDepth, Pixel).r + ScreenToDepth.x);\n"
2534 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2535 "       // decode viewspace pixel normal\n"
2536 "       half4 normalmap = texRECT(Texture_ScreenNormalMap, Pixel);\n"
2537 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2538 "       // surfacenormal = pixel normal in viewspace\n"
2539 "       // LightVector = pixel to light in viewspace\n"
2540 "       // CubeVector = position in lightspace\n"
2541 "       // eyevector = pixel to view in viewspace\n"
2542 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2543 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2544 "#ifdef USEDIFFUSE\n"
2545 "       // calculate diffuse shading\n"
2546 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2547 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2548 "#endif\n"
2549 "#ifdef USESPECULAR\n"
2550 "       // calculate directional shading\n"
2551 "       float3 eyevector = position * -1.0;\n"
2552 "#  ifdef USEEXACTSPECULARMATH\n"
2553 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2554 "#  else\n"
2555 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2556 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2557 "#  endif\n"
2558 "#endif\n"
2559 "\n"
2560 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2561 "       fade *= ShadowMapCompare(CubeVector,\n"
2562 "# if defined(USESHADOWMAP2D)\n"
2563 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2564 "# endif\n"
2565 "# if defined(USESHADOWMAPRECT)\n"
2566 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2567 "# endif\n"
2568 "# if defined(USESHADOWMAPCUBE)\n"
2569 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2570 "# endif\n"
2571 "\n"
2572 "#ifdef USESHADOWMAPVSDCT\n"
2573 ", Texture_CubeProjection\n"
2574 "#endif\n"
2575 "       );\n"
2576 "#endif\n"
2577 "\n"
2578 "#ifdef USEDIFFUSE\n"
2579 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2580 "#else\n"
2581 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2582 "#endif\n"
2583 "#ifdef USESPECULAR\n"
2584 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2585 "#else\n"
2586 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2587 "#endif\n"
2588 "\n"
2589 "# ifdef USECUBEFILTER\n"
2590 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2591 "       gl_FragData0 *= cubecolor;\n"
2592 "       gl_FragData1 *= cubecolor;\n"
2593 "# endif\n"
2594 "}\n"
2595 "#endif // FRAGMENT_SHADER\n"
2596 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2597 "\n"
2598 "\n"
2599 "\n"
2600 "\n"
2601 "#ifdef VERTEX_SHADER\n"
2602 "void main\n"
2603 "(\n"
2604 "float4 gl_Vertex : POSITION,\n"
2605 "uniform float4x4 ModelViewProjectionMatrix,\n"
2606 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2607 "float4 gl_Color : COLOR0,\n"
2608 "#endif\n"
2609 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2610 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2611 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2612 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2613 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2614 "\n"
2615 "uniform float3 EyePosition,\n"
2616 "uniform mat4 TexMatrix,\n"
2617 "#ifdef USEVERTEXTEXTUREBLEND\n"
2618 "uniform mat4 BackgroundTexMatrix,\n"
2619 "#endif\n"
2620 "#ifdef MODE_LIGHTSOURCE\n"
2621 "uniform mat4 ModelToLight,\n"
2622 "#endif\n"
2623 "#ifdef MODE_LIGHTSOURCE\n"
2624 "uniform float3 LightPosition,\n"
2625 "#endif\n"
2626 "#ifdef MODE_LIGHTDIRECTION\n"
2627 "uniform float3 LightDir,\n"
2628 "#endif\n"
2629 "uniform float4 FogPlane,\n"
2630 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2631 "uniform float3 LightPosition,\n"
2632 "#endif\n"
2633 "\n"
2634 "out float4 gl_FrontColor : COLOR,\n"
2635 "out float4 TexCoordBoth : TEXCOORD0,\n"
2636 "#ifdef USELIGHTMAP\n"
2637 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2638 "#endif\n"
2639 "#ifdef USEEYEVECTOR\n"
2640 "out float3 EyeVector : TEXCOORD2,\n"
2641 "#endif\n"
2642 "#ifdef USEREFLECTION\n"
2643 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2644 "#endif\n"
2645 "#ifdef USEFOG\n"
2646 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2647 "#endif\n"
2648 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2649 "out float3 LightVector : TEXCOORD5,\n"
2650 "#endif\n"
2651 "#ifdef MODE_LIGHTSOURCE\n"
2652 "out float3 CubeVector : TEXCOORD3,\n"
2653 "#endif\n"
2654 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2655 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2656 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2657 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2658 "#endif\n"
2659 "out float4 gl_Position : POSITION\n"
2660 ")\n"
2661 "{\n"
2662 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2663 "       gl_FrontColor = gl_Color;\n"
2664 "#endif\n"
2665 "       // copy the surface texcoord\n"
2666 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2667 "#ifdef USEVERTEXTEXTUREBLEND\n"
2668 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2669 "#endif\n"
2670 "#ifdef USELIGHTMAP\n"
2671 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2672 "#endif\n"
2673 "\n"
2674 "#ifdef MODE_LIGHTSOURCE\n"
2675 "       // transform vertex position into light attenuation/cubemap space\n"
2676 "       // (-1 to +1 across the light box)\n"
2677 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2678 "\n"
2679 "# ifdef USEDIFFUSE\n"
2680 "       // transform unnormalized light direction into tangent space\n"
2681 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2682 "       //  normalize it per pixel)\n"
2683 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2684 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2685 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2686 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2687 "# endif\n"
2688 "#endif\n"
2689 "\n"
2690 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2691 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2692 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2693 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2694 "#endif\n"
2695 "\n"
2696 "       // transform unnormalized eye direction into tangent space\n"
2697 "#ifdef USEEYEVECTOR\n"
2698 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2699 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2700 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2701 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2702 "#endif\n"
2703 "\n"
2704 "#ifdef USEFOG\n"
2705 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2706 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2710 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2711 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2712 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2713 "#endif\n"
2714 "\n"
2715 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2716 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2717 "\n"
2718 "#ifdef USEREFLECTION\n"
2719 "       ModelViewProjectionPosition = gl_Position;\n"
2720 "#endif\n"
2721 "}\n"
2722 "#endif // VERTEX_SHADER\n"
2723 "\n"
2724 "\n"
2725 "\n"
2726 "\n"
2727 "#ifdef FRAGMENT_SHADER\n"
2728 "void main\n"
2729 "(\n"
2730 "#ifdef USEDEFERREDLIGHTMAP\n"
2731 "float2 Pixel : WPOS,\n"
2732 "#endif\n"
2733 "float4 gl_FrontColor : COLOR,\n"
2734 "float4 TexCoordBoth : TEXCOORD0,\n"
2735 "#ifdef USELIGHTMAP\n"
2736 "float2 TexCoordLightmap : TEXCOORD1,\n"
2737 "#endif\n"
2738 "#ifdef USEEYEVECTOR\n"
2739 "float3 EyeVector : TEXCOORD2,\n"
2740 "#endif\n"
2741 "#ifdef USEREFLECTION\n"
2742 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2743 "#endif\n"
2744 "#ifdef USEFOG\n"
2745 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2746 "#endif\n"
2747 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2748 "float3 LightVector : TEXCOORD5,\n"
2749 "#endif\n"
2750 "#ifdef MODE_LIGHTSOURCE\n"
2751 "float3 CubeVector : TEXCOORD3,\n"
2752 "#endif\n"
2753 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2754 "float4 ModelViewPosition : TEXCOORD0,\n"
2755 "#endif\n"
2756 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2757 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2758 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2759 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2760 "#endif\n"
2761 "\n"
2762 "uniform sampler2D Texture_Normal,\n"
2763 "uniform sampler2D Texture_Color,\n"
2764 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2765 "uniform sampler2D Texture_Gloss,\n"
2766 "#endif\n"
2767 "#ifdef USEGLOW\n"
2768 "uniform sampler2D Texture_Glow,\n"
2769 "#endif\n"
2770 "#ifdef USEVERTEXTEXTUREBLEND\n"
2771 "uniform sampler2D Texture_SecondaryNormal,\n"
2772 "uniform sampler2D Texture_SecondaryColor,\n"
2773 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2774 "uniform sampler2D Texture_SecondaryGloss,\n"
2775 "#endif\n"
2776 "#ifdef USEGLOW\n"
2777 "uniform sampler2D Texture_SecondaryGlow,\n"
2778 "#endif\n"
2779 "#endif\n"
2780 "#ifdef USECOLORMAPPING\n"
2781 "uniform sampler2D Texture_Pants,\n"
2782 "uniform sampler2D Texture_Shirt,\n"
2783 "#endif\n"
2784 "#ifdef USEFOG\n"
2785 "uniform sampler2D Texture_FogMask,\n"
2786 "#endif\n"
2787 "#ifdef USELIGHTMAP\n"
2788 "uniform sampler2D Texture_Lightmap,\n"
2789 "#endif\n"
2790 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2791 "uniform sampler2D Texture_Deluxemap,\n"
2792 "#endif\n"
2793 "#ifdef USEREFLECTION\n"
2794 "uniform sampler2D Texture_Reflection,\n"
2795 "#endif\n"
2796 "\n"
2797 "//#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2798 "uniform samplerRECT Texture_ScreenDepth,\n"
2799 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2800 "//#endif\n"
2801 "#ifdef USEDEFERREDLIGHTMAP\n"
2802 "uniform samplerRECT Texture_ScreenDiffuse,\n"
2803 "uniform samplerRECT Texture_ScreenSpecular,\n"
2804 "#endif\n"
2805 "\n"
2806 "#ifdef USECOLORMAPPING\n"
2807 "uniform half3 Color_Pants,\n"
2808 "uniform half3 Color_Shirt,\n"
2809 "#endif\n"
2810 "#ifdef USEFOG\n"
2811 "uniform float3 FogColor,\n"
2812 "uniform float FogRangeRecip,\n"
2813 "uniform float FogPlaneViewDist,\n"
2814 "uniform float FogHeightFade,\n"
2815 "#endif\n"
2816 "\n"
2817 "#ifdef USEOFFSETMAPPING\n"
2818 "uniform float OffsetMapping_Scale,\n"
2819 "#endif\n"
2820 "\n"
2821 "#ifdef USEDEFERREDLIGHTMAP\n"
2822 "uniform half3 DeferredMod_Diffuse,\n"
2823 "uniform half3 DeferredMod_Specular,\n"
2824 "#endif\n"
2825 "uniform half3 Color_Ambient,\n"
2826 "uniform half3 Color_Diffuse,\n"
2827 "uniform half3 Color_Specular,\n"
2828 "uniform half SpecularPower,\n"
2829 "#ifdef USEGLOW\n"
2830 "uniform half3 Color_Glow,\n"
2831 "#endif\n"
2832 "uniform half Alpha,\n"
2833 "#ifdef USEREFLECTION\n"
2834 "uniform float4 DistortScaleRefractReflect,\n"
2835 "uniform float4 ScreenScaleRefractReflect,\n"
2836 "uniform float4 ScreenCenterRefractReflect,\n"
2837 "uniform half4 ReflectColor,\n"
2838 "#endif\n"
2839 "#ifdef MODE_LIGHTDIRECTION\n"
2840 "uniform half3 LightColor,\n"
2841 "#endif\n"
2842 "#ifdef MODE_LIGHTSOURCE\n"
2843 "uniform half3 LightColor,\n"
2844 "#endif\n"
2845 "\n"
2846 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2847 "uniform sampler2D Texture_Attenuation,\n"
2848 "uniform samplerCUBE Texture_Cube,\n"
2849 "\n"
2850 "#ifdef USESHADOWMAPRECT\n"
2851 "# ifdef USESHADOWSAMPLER\n"
2852 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2853 "# else\n"
2854 "uniform samplerRECT Texture_ShadowMapRect,\n"
2855 "# endif\n"
2856 "#endif\n"
2857 "\n"
2858 "#ifdef USESHADOWMAP2D\n"
2859 "# ifdef USESHADOWSAMPLER\n"
2860 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2861 "# else\n"
2862 "uniform sampler2D Texture_ShadowMap2D,\n"
2863 "# endif\n"
2864 "#endif\n"
2865 "\n"
2866 "#ifdef USESHADOWMAPVSDCT\n"
2867 "uniform samplerCUBE Texture_CubeProjection,\n"
2868 "#endif\n"
2869 "\n"
2870 "#ifdef USESHADOWMAPCUBE\n"
2871 "# ifdef USESHADOWSAMPLER\n"
2872 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2873 "# else\n"
2874 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2875 "# endif\n"
2876 "#endif\n"
2877 "\n"
2878 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2879 "uniform float2 ShadowMap_TextureScale,\n"
2880 "uniform float4 ShadowMap_Parameters,\n"
2881 "#endif\n"
2882 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2883 "\n"
2884 "out float4 gl_FragColor : COLOR\n"
2885 ")\n"
2886 "{\n"
2887 "       float2 TexCoord = TexCoordBoth.xy;\n"
2888 "#ifdef USEVERTEXTEXTUREBLEND\n"
2889 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2890 "#endif\n"
2891 "#ifdef USEOFFSETMAPPING\n"
2892 "       // apply offsetmapping\n"
2893 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2894 "#define TexCoord TexCoordOffset\n"
2895 "#endif\n"
2896 "\n"
2897 "       // combine the diffuse textures (base, pants, shirt)\n"
2898 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2899 "#ifdef USEALPHAKILL\n"
2900 "       if (color.a < 0.5)\n"
2901 "               discard;\n"
2902 "#endif\n"
2903 "       color.a *= Alpha;\n"
2904 "#ifdef USECOLORMAPPING\n"
2905 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2906 "#endif\n"
2907 "#ifdef USEVERTEXTEXTUREBLEND\n"
2908 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2909 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2910 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2911 "       color.rgb = half3(mix(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2912 "       color.a = 1.0;\n"
2913 "       //color = mix(half4(1, 0, 0, 1), color, terrainblend);\n"
2914 "#endif\n"
2915 "\n"
2916 "       // get the surface normal\n"
2917 "#ifdef USEVERTEXTEXTUREBLEND\n"
2918 "       half3 surfacenormal = normalize(half3(mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2919 "#else\n"
2920 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2921 "#endif\n"
2922 "\n"
2923 "       // get the material colors\n"
2924 "       half3 diffusetex = color.rgb;\n"
2925 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2926 "# ifdef USEVERTEXTEXTUREBLEND\n"
2927 "       half3 glosstex = half3(mix(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2928 "# else\n"
2929 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2930 "# endif\n"
2931 "#endif\n"
2932 "\n"
2933 "\n"
2934 "\n"
2935 "\n"
2936 "#ifdef MODE_LIGHTSOURCE\n"
2937 "       // light source\n"
2938 "       half3 lightnormal = half3(normalize(LightVector));\n"
2939 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2940 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2941 "#ifdef USESPECULAR\n"
2942 "#ifdef USEEXACTSPECULARMATH\n"
2943 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2944 "#else\n"
2945 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2946 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2947 "#endif\n"
2948 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2949 "#endif\n"
2950 "       color.rgb *= LightColor;\n"
2951 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2952 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2953 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2954 "# if defined(USESHADOWMAP2D)\n"
2955 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2956 "# endif\n"
2957 "# if defined(USESHADOWMAPRECT)\n"
2958 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2959 "# endif\n"
2960 "# if defined(USESHADOWMAPCUBE)\n"
2961 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2962 "# endif\n"
2963 "\n"
2964 "#ifdef USESHADOWMAPVSDCT\n"
2965 ", Texture_CubeProjection\n"
2966 "#endif\n"
2967 "       );\n"
2968 "\n"
2969 "#endif\n"
2970 "# ifdef USECUBEFILTER\n"
2971 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2972 "# endif\n"
2973 "#endif // MODE_LIGHTSOURCE\n"
2974 "\n"
2975 "\n"
2976 "\n"
2977 "\n"
2978 "#ifdef MODE_LIGHTDIRECTION\n"
2979 "#define SHADING\n"
2980 "       half3 lightnormal = half3(normalize(LightVector));\n"
2981 "#define lightcolor LightColor\n"
2982 "#endif // MODE_LIGHTDIRECTION\n"
2983 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2984 "#define SHADING\n"
2985 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
2986 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
2987 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
2988 "       // convert modelspace light vector to tangentspace\n"
2989 "       half3 lightnormal;\n"
2990 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
2991 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
2992 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
2993 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
2994 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
2995 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
2996 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
2997 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
2998 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
2999 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3000 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3001 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3002 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3003 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3004 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3005 "#define SHADING\n"
3006 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3007 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3008 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3009 "#endif\n"
3010 "\n"
3011 "\n"
3012 "\n"
3013 "\n"
3014 "#ifdef MODE_LIGHTMAP\n"
3015 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3016 "#endif // MODE_LIGHTMAP\n"
3017 "#ifdef MODE_VERTEXCOLOR\n"
3018 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3019 "#endif // MODE_VERTEXCOLOR\n"
3020 "#ifdef MODE_FLATCOLOR\n"
3021 "       color.rgb = diffusetex * Color_Ambient;\n"
3022 "#endif // MODE_FLATCOLOR\n"
3023 "\n"
3024 "\n"
3025 "\n"
3026 "\n"
3027 "#ifdef SHADING\n"
3028 "# ifdef USEDIFFUSE\n"
3029 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3030 "#  ifdef USESPECULAR\n"
3031 "#   ifdef USEEXACTSPECULARMATH\n"
3032 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3033 "#   else\n"
3034 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3035 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3036 "#   endif\n"
3037 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3038 "#  else\n"
3039 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3040 "#  endif\n"
3041 "# else\n"
3042 "       color.rgb = diffusetex * Color_Ambient;\n"
3043 "# endif\n"
3044 "#endif\n"
3045 "\n"
3046 "#ifdef USEDEFERREDLIGHTMAP\n"
3047 "       color.rgb += diffusetex * half3(texRECT(Texture_ScreenDiffuse, Pixel)) * DeferredMod_Diffuse;\n"
3048 "       color.rgb += glosstex * half3(texRECT(Texture_ScreenSpecular, Pixel)) * DeferredMod_Specular;\n"
3049 "       color.rgb = half3(texRECT(Texture_ScreenDepth, Pixel));\n"
3050 "#endif\n"
3051 "\n"
3052 "#ifdef USEGLOW\n"
3053 "#ifdef USEVERTEXTEXTUREBLEND\n"
3054 "       color.rgb += mix(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3055 "#else\n"
3056 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3057 "#endif\n"
3058 "#endif\n"
3059 "\n"
3060 "#ifdef USEFOG\n"
3061 "#ifdef MODE_LIGHTSOURCE\n"
3062 "       color.rgb *= half(FogVertex());\n"
3063 "#else\n"
3064 "       color.rgb = mix(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3065 "#endif\n"
3066 "#endif\n"
3067 "\n"
3068 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3069 "#ifdef USEREFLECTION\n"
3070 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3071 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3072 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3073 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3074 "       // FIXME temporary hack to detect the case that the reflection\n"
3075 "       // gets blackened at edges due to leaving the area that contains actual\n"
3076 "       // content.\n"
3077 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3078 "       // 'appening.\n"
3079 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3080 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3081 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3082 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3083 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3084 "       color.rgb = mix(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3085 "#endif\n"
3086 "\n"
3087 "       gl_FragColor = float4(color);\n"
3088 "}\n"
3089 "#endif // FRAGMENT_SHADER\n"
3090 "\n"
3091 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3092 "#endif // !MODE_DEFERREDGEOMETRY\n"
3093 "#endif // !MODE_WATER\n"
3094 "#endif // !MODE_REFRACTION\n"
3095 "#endif // !MODE_BLOOMBLUR\n"
3096 "#endif // !MODE_GENERIC\n"
3097 "#endif // !MODE_POSTPROCESS\n"
3098 "#endif // !MODE_SHOWDEPTH\n"
3099 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3100 ;
3101
3102 //=======================================================================================================================================================
3103
3104 typedef struct shaderpermutationinfo_s
3105 {
3106         const char *pretext;
3107         const char *name;
3108 }
3109 shaderpermutationinfo_t;
3110
3111 typedef struct shadermodeinfo_s
3112 {
3113         const char *vertexfilename;
3114         const char *geometryfilename;
3115         const char *fragmentfilename;
3116         const char *pretext;
3117         const char *name;
3118 }
3119 shadermodeinfo_t;
3120
3121 typedef enum shaderpermutation_e
3122 {
3123         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3124         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3125         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3126         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3127         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3128         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3129         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3130         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3131         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3132         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3133         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3134         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3135         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3136         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3137         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3138         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3139         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3140         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3141         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3142         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3143         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3144         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3145         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3146         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3147         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3148         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3149         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3150         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3151 }
3152 shaderpermutation_t;
3153
3154 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3155 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3156 {
3157         {"#define USEDIFFUSE\n", " diffuse"},
3158         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3159         {"#define USEVIEWTINT\n", " viewtint"},
3160         {"#define USECOLORMAPPING\n", " colormapping"},
3161         {"#define USESATURATION\n", " saturation"},
3162         {"#define USEFOGINSIDE\n", " foginside"},
3163         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3164         {"#define USEGAMMARAMPS\n", " gammaramps"},
3165         {"#define USECUBEFILTER\n", " cubefilter"},
3166         {"#define USEGLOW\n", " glow"},
3167         {"#define USEBLOOM\n", " bloom"},
3168         {"#define USESPECULAR\n", " specular"},
3169         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3170         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3171         {"#define USEREFLECTION\n", " reflection"},
3172         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3173         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3174         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3175         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3176         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3177         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3178         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3179         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3180         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3181         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3182         {"#define USEALPHAKILL\n", " alphakill"},
3183 };
3184
3185 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3186 typedef enum shadermode_e
3187 {
3188         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3189         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3190         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3191         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3192         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3193         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3194         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3195         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3196         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3197         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3198         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3199         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3200         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3201         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3202         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3203         SHADERMODE_COUNT
3204 }
3205 shadermode_t;
3206
3207 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3208 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3209 {
3210         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3211         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3212         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3213         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3214         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3215         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3216         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3217         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3218         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3219         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3220         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3221         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3222         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3223         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3224         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3225 };
3226
3227 #ifdef SUPPORTCG
3228 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3229 {
3230         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3231         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3232         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3233         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3234         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3235         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3236         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3237         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3238         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3239         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3240         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3241         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3242         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3243         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3244         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3245 };
3246 #endif
3247
3248 struct r_glsl_permutation_s;
3249 typedef struct r_glsl_permutation_s
3250 {
3251         /// hash lookup data
3252         struct r_glsl_permutation_s *hashnext;
3253         unsigned int mode;
3254         unsigned int permutation;
3255
3256         /// indicates if we have tried compiling this permutation already
3257         qboolean compiled;
3258         /// 0 if compilation failed
3259         int program;
3260         /// locations of detected uniforms in program object, or -1 if not found
3261         int loc_Texture_First;
3262         int loc_Texture_Second;
3263         int loc_Texture_GammaRamps;
3264         int loc_Texture_Normal;
3265         int loc_Texture_Color;
3266         int loc_Texture_Gloss;
3267         int loc_Texture_Glow;
3268         int loc_Texture_SecondaryNormal;
3269         int loc_Texture_SecondaryColor;
3270         int loc_Texture_SecondaryGloss;
3271         int loc_Texture_SecondaryGlow;
3272         int loc_Texture_Pants;
3273         int loc_Texture_Shirt;
3274         int loc_Texture_FogMask;
3275         int loc_Texture_Lightmap;
3276         int loc_Texture_Deluxemap;
3277         int loc_Texture_Attenuation;
3278         int loc_Texture_Cube;
3279         int loc_Texture_Refraction;
3280         int loc_Texture_Reflection;
3281         int loc_Texture_ShadowMapRect;
3282         int loc_Texture_ShadowMapCube;
3283         int loc_Texture_ShadowMap2D;
3284         int loc_Texture_CubeProjection;
3285         int loc_Texture_ScreenDepth;
3286         int loc_Texture_ScreenNormalMap;
3287         int loc_Texture_ScreenDiffuse;
3288         int loc_Texture_ScreenSpecular;
3289         int loc_Alpha;
3290         int loc_BloomBlur_Parameters;
3291         int loc_ClientTime;
3292         int loc_Color_Ambient;
3293         int loc_Color_Diffuse;
3294         int loc_Color_Specular;
3295         int loc_Color_Glow;
3296         int loc_Color_Pants;
3297         int loc_Color_Shirt;
3298         int loc_DeferredColor_Ambient;
3299         int loc_DeferredColor_Diffuse;
3300         int loc_DeferredColor_Specular;
3301         int loc_DeferredMod_Diffuse;
3302         int loc_DeferredMod_Specular;
3303         int loc_DistortScaleRefractReflect;
3304         int loc_EyePosition;
3305         int loc_FogColor;
3306         int loc_FogHeightFade;
3307         int loc_FogPlane;
3308         int loc_FogPlaneViewDist;
3309         int loc_FogRangeRecip;
3310         int loc_LightColor;
3311         int loc_LightDir;
3312         int loc_LightPosition;
3313         int loc_OffsetMapping_Scale;
3314         int loc_PixelSize;
3315         int loc_ReflectColor;
3316         int loc_ReflectFactor;
3317         int loc_ReflectOffset;
3318         int loc_RefractColor;
3319         int loc_Saturation;
3320         int loc_ScreenCenterRefractReflect;
3321         int loc_ScreenScaleRefractReflect;
3322         int loc_ScreenToDepth;
3323         int loc_ShadowMap_Parameters;
3324         int loc_ShadowMap_TextureScale;
3325         int loc_SpecularPower;
3326         int loc_UserVec1;
3327         int loc_UserVec2;
3328         int loc_UserVec3;
3329         int loc_UserVec4;
3330         int loc_ViewTintColor;
3331         int loc_ViewToLight;
3332         int loc_ModelToLight;
3333         int loc_TexMatrix;
3334         int loc_BackgroundTexMatrix;
3335         int loc_ModelViewProjectionMatrix;
3336         int loc_ModelViewMatrix;
3337 }
3338 r_glsl_permutation_t;
3339
3340 #define SHADERPERMUTATION_HASHSIZE 256
3341
3342 /// information about each possible shader permutation
3343 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3344 /// currently selected permutation
3345 r_glsl_permutation_t *r_glsl_permutation;
3346 /// storage for permutations linked in the hash table
3347 memexpandablearray_t r_glsl_permutationarray;
3348
3349 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3350 {
3351         //unsigned int hashdepth = 0;
3352         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3353         r_glsl_permutation_t *p;
3354         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3355         {
3356                 if (p->mode == mode && p->permutation == permutation)
3357                 {
3358                         //if (hashdepth > 10)
3359                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3360                         return p;
3361                 }
3362                 //hashdepth++;
3363         }
3364         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3365         p->mode = mode;
3366         p->permutation = permutation;
3367         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3368         r_glsl_permutationhash[mode][hashindex] = p;
3369         //if (hashdepth > 10)
3370         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3371         return p;
3372 }
3373
3374 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3375 {
3376         char *shaderstring;
3377         if (!filename || !filename[0])
3378                 return NULL;
3379         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3380         if (shaderstring)
3381         {
3382                 if (printfromdisknotice)
3383                         Con_DPrintf("from disk %s... ", filename);
3384                 return shaderstring;
3385         }
3386         else if (!strcmp(filename, "glsl/default.glsl"))
3387         {
3388                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3389                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3390         }
3391         return shaderstring;
3392 }
3393
3394 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3395 {
3396         int i;
3397         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3398         int vertstrings_count = 0;
3399         int geomstrings_count = 0;
3400         int fragstrings_count = 0;
3401         char *vertexstring, *geometrystring, *fragmentstring;
3402         const char *vertstrings_list[32+3];
3403         const char *geomstrings_list[32+3];
3404         const char *fragstrings_list[32+3];
3405         char permutationname[256];
3406
3407         if (p->compiled)
3408                 return;
3409         p->compiled = true;
3410         p->program = 0;
3411
3412         permutationname[0] = 0;
3413         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3414         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3415         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3416
3417         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3418
3419         // the first pretext is which type of shader to compile as
3420         // (later these will all be bound together as a program object)
3421         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3422         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3423         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3424
3425         // the second pretext is the mode (for example a light source)
3426         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3427         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3428         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3429         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3430
3431         // now add all the permutation pretexts
3432         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3433         {
3434                 if (permutation & (1<<i))
3435                 {
3436                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3437                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3438                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3439                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3440                 }
3441                 else
3442                 {
3443                         // keep line numbers correct
3444                         vertstrings_list[vertstrings_count++] = "\n";
3445                         geomstrings_list[geomstrings_count++] = "\n";
3446                         fragstrings_list[fragstrings_count++] = "\n";
3447                 }
3448         }
3449
3450         // now append the shader text itself
3451         vertstrings_list[vertstrings_count++] = vertexstring;
3452         geomstrings_list[geomstrings_count++] = geometrystring;
3453         fragstrings_list[fragstrings_count++] = fragmentstring;
3454
3455         // if any sources were NULL, clear the respective list
3456         if (!vertexstring)
3457                 vertstrings_count = 0;
3458         if (!geometrystring)
3459                 geomstrings_count = 0;
3460         if (!fragmentstring)
3461                 fragstrings_count = 0;
3462
3463         // compile the shader program
3464         if (vertstrings_count + geomstrings_count + fragstrings_count)
3465                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3466         if (p->program)
3467         {
3468                 CHECKGLERROR
3469                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3470                 // look up all the uniform variable names we care about, so we don't
3471                 // have to look them up every time we set them
3472
3473                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3474                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3475                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3476                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3477                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3478                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3479                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3480                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3481                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3482                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3483                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3484                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3485                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3486                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3487                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3488                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3489                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3490                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3491                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3492                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3493                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3494                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3495                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3496                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3497                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3498                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3499                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3500                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3501                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3502                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3503                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3504                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3505                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3506                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3507                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3508                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3509                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3510                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3511                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3512                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3513                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3514                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3515                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3516                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3517                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3518                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3519                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3520                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3521                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3522                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3523                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3524                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3525                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3526                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3527                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3528                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3529                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3530                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3531                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3532                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3533                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3534                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3535                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3536                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3537                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3538                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3539                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3540                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3541                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3542                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3543                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3544                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3545                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3546                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3547                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3548                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3549                 // initialize the samplers to refer to the texture units we use
3550                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3551                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3552                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3553                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3554                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3555                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3556                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3557                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3558                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3559                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3560                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3561                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3562                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3563                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3564                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3565                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3566                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3567                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3568                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3569                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3570                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3571                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3572                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3573                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3574                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3575                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3576                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3577                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3578                 CHECKGLERROR
3579                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3580         }
3581         else
3582                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3583
3584         // free the strings
3585         if (vertexstring)
3586                 Mem_Free(vertexstring);
3587         if (geometrystring)
3588                 Mem_Free(geometrystring);
3589         if (fragmentstring)
3590                 Mem_Free(fragmentstring);
3591 }
3592
3593 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3594 {
3595         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3596         if (r_glsl_permutation != perm)
3597         {
3598                 r_glsl_permutation = perm;
3599                 if (!r_glsl_permutation->program)
3600                 {
3601                         if (!r_glsl_permutation->compiled)
3602                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3603                         if (!r_glsl_permutation->program)
3604                         {
3605                                 // remove features until we find a valid permutation
3606                                 int i;
3607                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3608                                 {
3609                                         // reduce i more quickly whenever it would not remove any bits
3610                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3611                                         if (!(permutation & j))
3612                                                 continue;
3613                                         permutation -= j;
3614                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3615                                         if (!r_glsl_permutation->compiled)
3616                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3617                                         if (r_glsl_permutation->program)
3618                                                 break;
3619                                 }
3620                                 if (i >= SHADERPERMUTATION_COUNT)
3621                                 {
3622                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3623                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3624                                         qglUseProgramObjectARB(0);CHECKGLERROR
3625                                         return; // no bit left to clear, entire mode is broken
3626                                 }
3627                         }
3628                 }
3629                 CHECKGLERROR
3630                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3631         }
3632         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3633         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, specularscale, specularscale, 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, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
4670                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
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 * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * 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, specularscale, specularscale, 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, r_refdef.lightmapintensity, r_refdef.lightmapintensity);CHECKCGERROR
4806                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);CHECKCGERROR
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 * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * 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         r_frame++; // used only by R_GetCurrentTexture
7366
7367         R_ResetViewRendering3D();
7368
7369         R_ClearScreen(r_refdef.fogenabled);
7370         if (r_timereport_active)
7371                 R_TimeReport("viewclear");
7372 }
7373
7374 static void R_BlendView(void)
7375 {
7376         unsigned int permutation;
7377         float uservecs[4][4];
7378
7379         switch (vid.renderpath)
7380         {
7381         case RENDERPATH_GL20:
7382         case RENDERPATH_CGGL:
7383                 permutation =
7384                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7385                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7386                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7387                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7388                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7389
7390                 if (r_bloomstate.texture_screen)
7391                 {
7392                         // make sure the buffer is available
7393                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7394
7395                         R_ResetViewRendering2D();
7396                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7397                         R_Mesh_ColorPointer(NULL, 0, 0);
7398
7399                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7400                         {
7401                                 // declare variables
7402                                 float speed;
7403                                 static float avgspeed;
7404
7405                                 speed = VectorLength(cl.movement_velocity);
7406
7407                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7408                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7409
7410                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7411                                 speed = bound(0, speed, 1);
7412                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7413
7414                                 // calculate values into a standard alpha
7415                                 cl.motionbluralpha = 1 - exp(-
7416                                                 (
7417                                                  (r_motionblur.value * speed / 80)
7418                                                  +
7419                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7420                                                 )
7421                                                 /
7422                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7423                                            );
7424
7425                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7426                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7427                                 // apply the blur
7428                                 if (cl.motionbluralpha > 0)
7429                                 {
7430                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7431                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7432                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7433                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7434                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7435                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7436                                 }
7437                         }
7438
7439                         // copy view into the screen texture
7440                         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);
7441                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7442                 }
7443                 else if (!r_bloomstate.texture_bloom)
7444                 {
7445                         // we may still have to do view tint...
7446                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7447                         {
7448                                 // apply a color tint to the whole view
7449                                 R_ResetViewRendering2D();
7450                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7451                                 R_Mesh_ColorPointer(NULL, 0, 0);
7452                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7453                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7454                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7455                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7456                         }
7457                         break; // no screen processing, no bloom, skip it
7458                 }
7459
7460                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7461                 {
7462                         // render simple bloom effect
7463                         // copy the screen and shrink it and darken it for the bloom process
7464                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7465                         // make the bloom texture
7466                         R_Bloom_MakeTexture();
7467                 }
7468
7469 #if _MSC_VER >= 1400
7470 #define sscanf sscanf_s
7471 #endif
7472                 memset(uservecs, 0, sizeof(uservecs));
7473                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7474                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7475                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7476                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7477
7478                 R_ResetViewRendering2D();
7479                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7480                 R_Mesh_ColorPointer(NULL, 0, 0);
7481                 GL_Color(1, 1, 1, 1);
7482                 GL_BlendFunc(GL_ONE, GL_ZERO);
7483                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7484                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7485
7486                 switch(vid.renderpath)
7487                 {
7488                 case RENDERPATH_GL20:
7489                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7490                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7491                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7492                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7493                         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]);
7494                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7495                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7496                         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]);
7497                         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]);
7498                         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]);
7499                         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]);
7500                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7501                         break;
7502                 case RENDERPATH_CGGL:
7503 #ifdef SUPPORTCG
7504                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7505                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7506                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7507                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7508                         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
7509                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7510                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7511                         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
7512                         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
7513                         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
7514                         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
7515                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7516 #endif
7517                         break;
7518                 default:
7519                         break;
7520                 }
7521                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7522                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7523                 break;
7524         case RENDERPATH_GL13:
7525         case RENDERPATH_GL11:
7526                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7527                 {
7528                         // apply a color tint to the whole view
7529                         R_ResetViewRendering2D();
7530                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7531                         R_Mesh_ColorPointer(NULL, 0, 0);
7532                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7533                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7534                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7535                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7536                 }
7537                 break;
7538         }
7539 }
7540
7541 matrix4x4_t r_waterscrollmatrix;
7542
7543 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7544 {
7545         if (r_refdef.fog_density)
7546         {
7547                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7548                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7549                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7550
7551                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7552                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7553                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7554                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7555
7556                 {
7557                         vec3_t fogvec;
7558                         VectorCopy(r_refdef.fogcolor, fogvec);
7559                         //   color.rgb *= ContrastBoost * SceneBrightness;
7560                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7561                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7562                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7563                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7564                 }
7565         }
7566 }
7567
7568 void R_UpdateVariables(void)
7569 {
7570         R_Textures_Frame();
7571
7572         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7573
7574         r_refdef.farclip = r_farclip_base.value;
7575         if (r_refdef.scene.worldmodel)
7576                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7577         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7578
7579         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7580                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7581         r_refdef.polygonfactor = 0;
7582         r_refdef.polygonoffset = 0;
7583         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7584         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7585
7586         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7587         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7588         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7589         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7590         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7591         if (r_showsurfaces.integer)
7592         {
7593                 r_refdef.scene.rtworld = false;
7594                 r_refdef.scene.rtworldshadows = false;
7595                 r_refdef.scene.rtdlight = false;
7596                 r_refdef.scene.rtdlightshadows = false;
7597                 r_refdef.lightmapintensity = 0;
7598         }
7599
7600         if (gamemode == GAME_NEHAHRA)
7601         {
7602                 if (gl_fogenable.integer)
7603                 {
7604                         r_refdef.oldgl_fogenable = true;
7605                         r_refdef.fog_density = gl_fogdensity.value;
7606                         r_refdef.fog_red = gl_fogred.value;
7607                         r_refdef.fog_green = gl_foggreen.value;
7608                         r_refdef.fog_blue = gl_fogblue.value;
7609                         r_refdef.fog_alpha = 1;
7610                         r_refdef.fog_start = 0;
7611                         r_refdef.fog_end = gl_skyclip.value;
7612                         r_refdef.fog_height = 1<<30;
7613                         r_refdef.fog_fadedepth = 128;
7614                 }
7615                 else if (r_refdef.oldgl_fogenable)
7616                 {
7617                         r_refdef.oldgl_fogenable = false;
7618                         r_refdef.fog_density = 0;
7619                         r_refdef.fog_red = 0;
7620                         r_refdef.fog_green = 0;
7621                         r_refdef.fog_blue = 0;
7622                         r_refdef.fog_alpha = 0;
7623                         r_refdef.fog_start = 0;
7624                         r_refdef.fog_end = 0;
7625                         r_refdef.fog_height = 1<<30;
7626                         r_refdef.fog_fadedepth = 128;
7627                 }
7628         }
7629
7630         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7631         r_refdef.fog_start = max(0, r_refdef.fog_start);
7632         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7633
7634         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7635
7636         if (r_refdef.fog_density && r_drawfog.integer)
7637         {
7638                 r_refdef.fogenabled = true;
7639                 // this is the point where the fog reaches 0.9986 alpha, which we
7640                 // consider a good enough cutoff point for the texture
7641                 // (0.9986 * 256 == 255.6)
7642                 if (r_fog_exp2.integer)
7643                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7644                 else
7645                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7646                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7647                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7648                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7649                 // fog color was already set
7650                 // update the fog texture
7651                 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)
7652                         R_BuildFogTexture();
7653         }
7654         else
7655                 r_refdef.fogenabled = false;
7656
7657         switch(vid.renderpath)
7658         {
7659         case RENDERPATH_GL20:
7660         case RENDERPATH_CGGL:
7661                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7662                 {
7663                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7664                         {
7665                                 // build GLSL gamma texture
7666 #define RAMPWIDTH 256
7667                                 unsigned short ramp[RAMPWIDTH * 3];
7668                                 unsigned char rampbgr[RAMPWIDTH][4];
7669                                 int i;
7670
7671                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7672
7673                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7674                                 for(i = 0; i < RAMPWIDTH; ++i)
7675                                 {
7676                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7677                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7678                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7679                                         rampbgr[i][3] = 0;
7680                                 }
7681                                 if (r_texture_gammaramps)
7682                                 {
7683                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7684                                 }
7685                                 else
7686                                 {
7687                                         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);
7688                                 }
7689                         }
7690                 }
7691                 else
7692                 {
7693                         // remove GLSL gamma texture
7694                 }
7695                 break;
7696         case RENDERPATH_GL13:
7697         case RENDERPATH_GL11:
7698                 break;
7699         }
7700 }
7701
7702 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7703 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7704 /*
7705 ================
7706 R_SelectScene
7707 ================
7708 */
7709 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7710         if( scenetype != r_currentscenetype ) {
7711                 // store the old scenetype
7712                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7713                 r_currentscenetype = scenetype;
7714                 // move in the new scene
7715                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7716         }
7717 }
7718
7719 /*
7720 ================
7721 R_GetScenePointer
7722 ================
7723 */
7724 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7725 {
7726         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7727         if( scenetype == r_currentscenetype ) {
7728                 return &r_refdef.scene;
7729         } else {
7730                 return &r_scenes_store[ scenetype ];
7731         }
7732 }
7733
7734 /*
7735 ================
7736 R_RenderView
7737 ================
7738 */
7739 void R_RenderView(void)
7740 {
7741         if (r_timereport_active)
7742                 R_TimeReport("start");
7743         r_frame++; // used only by R_GetCurrentTexture
7744         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7745
7746         if (!r_drawentities.integer)
7747                 r_refdef.scene.numentities = 0;
7748
7749         R_AnimCache_ClearCache();
7750         R_FrameData_NewFrame();
7751
7752         if (r_refdef.view.isoverlay)
7753         {
7754                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7755                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7756                 R_TimeReport("depthclear");
7757
7758                 r_refdef.view.showdebug = false;
7759
7760                 r_waterstate.enabled = false;
7761                 r_waterstate.numwaterplanes = 0;
7762
7763                 R_RenderScene();
7764
7765                 CHECKGLERROR
7766                 return;
7767         }
7768
7769         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7770                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7771
7772         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7773
7774         // break apart the view matrix into vectors for various purposes
7775         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7776         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7777         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7778         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7779         // make an inverted copy of the view matrix for tracking sprites
7780         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7781
7782         R_Shadow_UpdateWorldLightSelection();
7783
7784         R_Bloom_StartFrame();
7785         R_Water_StartFrame();
7786
7787         CHECKGLERROR
7788         if (r_timereport_active)
7789                 R_TimeReport("viewsetup");
7790
7791         R_ResetViewRendering3D();
7792
7793         if (r_refdef.view.clear || r_refdef.fogenabled)
7794         {
7795                 R_ClearScreen(r_refdef.fogenabled);
7796                 if (r_timereport_active)
7797                         R_TimeReport("viewclear");
7798         }
7799         r_refdef.view.clear = true;
7800
7801         // this produces a bloom texture to be used in R_BlendView() later
7802         if (r_hdr.integer && r_bloomstate.bloomwidth)
7803                 R_HDR_RenderBloomTexture();
7804
7805         r_refdef.view.showdebug = true;
7806
7807         R_View_Update();
7808         if (r_timereport_active)
7809                 R_TimeReport("visibility");
7810
7811         r_waterstate.numwaterplanes = 0;
7812         if (r_waterstate.enabled)
7813                 R_RenderWaterPlanes();
7814
7815         R_RenderScene();
7816         r_waterstate.numwaterplanes = 0;
7817
7818         R_BlendView();
7819         if (r_timereport_active)
7820                 R_TimeReport("blendview");
7821
7822         GL_Scissor(0, 0, vid.width, vid.height);
7823         GL_ScissorTest(false);
7824         CHECKGLERROR
7825 }
7826
7827 void R_RenderWaterPlanes(void)
7828 {
7829         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7830         {
7831                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7832                 if (r_timereport_active)
7833                         R_TimeReport("waterworld");
7834         }
7835
7836         // don't let sound skip if going slow
7837         if (r_refdef.scene.extraupdate)
7838                 S_ExtraUpdate ();
7839
7840         R_DrawModelsAddWaterPlanes();
7841         if (r_timereport_active)
7842                 R_TimeReport("watermodels");
7843
7844         if (r_waterstate.numwaterplanes)
7845         {
7846                 R_Water_ProcessPlanes();
7847                 if (r_timereport_active)
7848                         R_TimeReport("waterscenes");
7849         }
7850 }
7851
7852 extern void R_DrawLightningBeams (void);
7853 extern void VM_CL_AddPolygonsToMeshQueue (void);
7854 extern void R_DrawPortals (void);
7855 extern cvar_t cl_locs_show;
7856 static void R_DrawLocs(void);
7857 static void R_DrawEntityBBoxes(void);
7858 static void R_DrawModelDecals(void);
7859 extern cvar_t cl_decals_newsystem;
7860 extern qboolean r_shadow_usingdeferredprepass;
7861 void R_RenderScene(void)
7862 {
7863         r_refdef.stats.renders++;
7864
7865         R_UpdateFogColor();
7866
7867         // don't let sound skip if going slow
7868         if (r_refdef.scene.extraupdate)
7869                 S_ExtraUpdate ();
7870
7871         R_MeshQueue_BeginScene();
7872
7873         R_SkyStartFrame();
7874
7875         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);
7876
7877         if (cl.csqc_vidvars.drawworld)
7878         {
7879                 // don't let sound skip if going slow
7880                 if (r_refdef.scene.extraupdate)
7881                         S_ExtraUpdate ();
7882
7883                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7884                 {
7885                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7886                         if (r_timereport_active)
7887                                 R_TimeReport("worldsky");
7888                 }
7889
7890                 if (R_DrawBrushModelsSky() && r_timereport_active)
7891                         R_TimeReport("bmodelsky");
7892
7893                 if (skyrendermasked && skyrenderlater)
7894                 {
7895                         // we have to force off the water clipping plane while rendering sky
7896                         R_SetupView(false);
7897                         R_Sky();
7898                         R_SetupView(true);
7899                         if (r_timereport_active)
7900                                 R_TimeReport("sky");
7901                 }
7902         }
7903
7904         R_AnimCache_CacheVisibleEntities();
7905         if (r_timereport_active)
7906                 R_TimeReport("animation");
7907
7908         R_Shadow_PrepareLights();
7909         if (r_timereport_active)
7910                 R_TimeReport("preparelights");
7911
7912         if (r_shadow_usingdeferredprepass)
7913                 R_Shadow_DrawPrepass();
7914
7915         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7916         {
7917                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7918                 if (r_timereport_active)
7919                         R_TimeReport("worlddepth");
7920         }
7921         if (r_depthfirst.integer >= 2)
7922         {
7923                 R_DrawModelsDepth();
7924                 if (r_timereport_active)
7925                         R_TimeReport("modeldepth");
7926         }
7927
7928         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7929         {
7930                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7931                 if (r_timereport_active)
7932                         R_TimeReport("world");
7933         }
7934
7935         // don't let sound skip if going slow
7936         if (r_refdef.scene.extraupdate)
7937                 S_ExtraUpdate ();
7938
7939         R_DrawModels();
7940         if (r_timereport_active)
7941                 R_TimeReport("models");
7942
7943         // don't let sound skip if going slow
7944         if (r_refdef.scene.extraupdate)
7945                 S_ExtraUpdate ();
7946
7947         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7948         {
7949                 R_DrawModelShadows();
7950                 R_ResetViewRendering3D();
7951                 // don't let sound skip if going slow
7952                 if (r_refdef.scene.extraupdate)
7953                         S_ExtraUpdate ();
7954         }
7955
7956         if (!r_shadow_usingdeferredprepass)
7957         {
7958                 R_Shadow_DrawLights();
7959                 if (r_timereport_active)
7960                         R_TimeReport("rtlights");
7961         }
7962
7963         // don't let sound skip if going slow
7964         if (r_refdef.scene.extraupdate)
7965                 S_ExtraUpdate ();
7966
7967         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7968         {
7969                 R_DrawModelShadows();
7970                 R_ResetViewRendering3D();
7971                 // don't let sound skip if going slow
7972                 if (r_refdef.scene.extraupdate)
7973                         S_ExtraUpdate ();
7974         }
7975
7976         if (cl.csqc_vidvars.drawworld)
7977         {
7978                 if (cl_decals_newsystem.integer)
7979                 {
7980                         R_DrawModelDecals();
7981                         if (r_timereport_active)
7982                                 R_TimeReport("modeldecals");
7983                 }
7984                 else
7985                 {
7986                         R_DrawDecals();
7987                         if (r_timereport_active)
7988                                 R_TimeReport("decals");
7989                 }
7990
7991                 R_DrawParticles();
7992                 if (r_timereport_active)
7993                         R_TimeReport("particles");
7994
7995                 R_DrawExplosions();
7996                 if (r_timereport_active)
7997                         R_TimeReport("explosions");
7998
7999                 R_DrawLightningBeams();
8000                 if (r_timereport_active)
8001                         R_TimeReport("lightning");
8002         }
8003
8004         VM_CL_AddPolygonsToMeshQueue();
8005
8006         if (r_refdef.view.showdebug)
8007         {
8008                 if (cl_locs_show.integer)
8009                 {
8010                         R_DrawLocs();
8011                         if (r_timereport_active)
8012                                 R_TimeReport("showlocs");
8013                 }
8014
8015                 if (r_drawportals.integer)
8016                 {
8017                         R_DrawPortals();
8018                         if (r_timereport_active)
8019                                 R_TimeReport("portals");
8020                 }
8021
8022                 if (r_showbboxes.value > 0)
8023                 {
8024                         R_DrawEntityBBoxes();
8025                         if (r_timereport_active)
8026                                 R_TimeReport("bboxes");
8027                 }
8028         }
8029
8030         R_MeshQueue_RenderTransparent();
8031         if (r_timereport_active)
8032                 R_TimeReport("drawtrans");
8033
8034         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))
8035         {
8036                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8037                 if (r_timereport_active)
8038                         R_TimeReport("worlddebug");
8039                 R_DrawModelsDebug();
8040                 if (r_timereport_active)
8041                         R_TimeReport("modeldebug");
8042         }
8043
8044         if (cl.csqc_vidvars.drawworld)
8045         {
8046                 R_Shadow_DrawCoronas();
8047                 if (r_timereport_active)
8048                         R_TimeReport("coronas");
8049         }
8050
8051         // don't let sound skip if going slow
8052         if (r_refdef.scene.extraupdate)
8053                 S_ExtraUpdate ();
8054
8055         R_ResetViewRendering2D();
8056 }
8057
8058 static const unsigned short bboxelements[36] =
8059 {
8060         5, 1, 3, 5, 3, 7,
8061         6, 2, 0, 6, 0, 4,
8062         7, 3, 2, 7, 2, 6,
8063         4, 0, 1, 4, 1, 5,
8064         4, 5, 7, 4, 7, 6,
8065         1, 0, 2, 1, 2, 3,
8066 };
8067
8068 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8069 {
8070         int i;
8071         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8072
8073         RSurf_ActiveWorldEntity();
8074
8075         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8076         GL_DepthMask(false);
8077         GL_DepthRange(0, 1);
8078         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8079         R_Mesh_ResetTextureState();
8080
8081         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8082         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8083         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8084         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8085         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8086         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8087         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8088         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8089         R_FillColors(color4f, 8, cr, cg, cb, ca);
8090         if (r_refdef.fogenabled)
8091         {
8092                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8093                 {
8094                         f1 = RSurf_FogVertex(v);
8095                         f2 = 1 - f1;
8096                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8097                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8098                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8099                 }
8100         }
8101         R_Mesh_VertexPointer(vertex3f, 0, 0);
8102         R_Mesh_ColorPointer(color4f, 0, 0);
8103         R_Mesh_ResetTextureState();
8104         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8105         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8106 }
8107
8108 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8109 {
8110         int i;
8111         float color[4];
8112         prvm_edict_t *edict;
8113         prvm_prog_t *prog_save = prog;
8114
8115         // this function draws bounding boxes of server entities
8116         if (!sv.active)
8117                 return;
8118
8119         GL_CullFace(GL_NONE);
8120         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8121
8122         prog = 0;
8123         SV_VM_Begin();
8124         for (i = 0;i < numsurfaces;i++)
8125         {
8126                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8127                 switch ((int)edict->fields.server->solid)
8128                 {
8129                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8130                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8131                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8132                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8133                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8134                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8135                 }
8136                 color[3] *= r_showbboxes.value;
8137                 color[3] = bound(0, color[3], 1);
8138                 GL_DepthTest(!r_showdisabledepthtest.integer);
8139                 GL_CullFace(r_refdef.view.cullface_front);
8140                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8141         }
8142         SV_VM_End();
8143         prog = prog_save;
8144 }
8145
8146 static void R_DrawEntityBBoxes(void)
8147 {
8148         int i;
8149         prvm_edict_t *edict;
8150         vec3_t center;
8151         prvm_prog_t *prog_save = prog;
8152
8153         // this function draws bounding boxes of server entities
8154         if (!sv.active)
8155                 return;
8156
8157         prog = 0;
8158         SV_VM_Begin();
8159         for (i = 0;i < prog->num_edicts;i++)
8160         {
8161                 edict = PRVM_EDICT_NUM(i);
8162                 if (edict->priv.server->free)
8163                         continue;
8164                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8165                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8166                         continue;
8167                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8168                         continue;
8169                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8170                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8171         }
8172         SV_VM_End();
8173         prog = prog_save;
8174 }
8175
8176 static const int nomodelelement3i[24] =
8177 {
8178         5, 2, 0,
8179         5, 1, 2,
8180         5, 0, 3,
8181         5, 3, 1,
8182         0, 2, 4,
8183         2, 1, 4,
8184         3, 0, 4,
8185         1, 3, 4
8186 };
8187
8188 static const unsigned short nomodelelement3s[24] =
8189 {
8190         5, 2, 0,
8191         5, 1, 2,
8192         5, 0, 3,
8193         5, 3, 1,
8194         0, 2, 4,
8195         2, 1, 4,
8196         3, 0, 4,
8197         1, 3, 4
8198 };
8199
8200 static const float nomodelvertex3f[6*3] =
8201 {
8202         -16,   0,   0,
8203          16,   0,   0,
8204           0, -16,   0,
8205           0,  16,   0,
8206           0,   0, -16,
8207           0,   0,  16
8208 };
8209
8210 static const float nomodelcolor4f[6*4] =
8211 {
8212         0.0f, 0.0f, 0.5f, 1.0f,
8213         0.0f, 0.0f, 0.5f, 1.0f,
8214         0.0f, 0.5f, 0.0f, 1.0f,
8215         0.0f, 0.5f, 0.0f, 1.0f,
8216         0.5f, 0.0f, 0.0f, 1.0f,
8217         0.5f, 0.0f, 0.0f, 1.0f
8218 };
8219
8220 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8221 {
8222         int i;
8223         float f1, f2, *c;
8224         float color4f[6*4];
8225
8226         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);
8227
8228         // this is only called once per entity so numsurfaces is always 1, and
8229         // surfacelist is always {0}, so this code does not handle batches
8230
8231         if (rsurface.ent_flags & RENDER_ADDITIVE)
8232         {
8233                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8234                 GL_DepthMask(false);
8235         }
8236         else if (rsurface.colormod[3] < 1)
8237         {
8238                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8239                 GL_DepthMask(false);
8240         }
8241         else
8242         {
8243                 GL_BlendFunc(GL_ONE, GL_ZERO);
8244                 GL_DepthMask(true);
8245         }
8246         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8247         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8248         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8249         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8250         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8251         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8252         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8253         R_Mesh_ColorPointer(color4f, 0, 0);
8254         for (i = 0, c = color4f;i < 6;i++, c += 4)
8255         {
8256                 c[0] *= rsurface.colormod[0];
8257                 c[1] *= rsurface.colormod[1];
8258                 c[2] *= rsurface.colormod[2];
8259                 c[3] *= rsurface.colormod[3];
8260         }
8261         if (r_refdef.fogenabled)
8262         {
8263                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8264                 {
8265                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8266                         f2 = 1 - f1;
8267                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8268                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8269                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8270                 }
8271         }
8272         R_Mesh_ResetTextureState();
8273         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8274 }
8275
8276 void R_DrawNoModel(entity_render_t *ent)
8277 {
8278         vec3_t org;
8279         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8280         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8281                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8282         else
8283                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8284 }
8285
8286 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8287 {
8288         vec3_t right1, right2, diff, normal;
8289
8290         VectorSubtract (org2, org1, normal);
8291
8292         // calculate 'right' vector for start
8293         VectorSubtract (r_refdef.view.origin, org1, diff);
8294         CrossProduct (normal, diff, right1);
8295         VectorNormalize (right1);
8296
8297         // calculate 'right' vector for end
8298         VectorSubtract (r_refdef.view.origin, org2, diff);
8299         CrossProduct (normal, diff, right2);
8300         VectorNormalize (right2);
8301
8302         vert[ 0] = org1[0] + width * right1[0];
8303         vert[ 1] = org1[1] + width * right1[1];
8304         vert[ 2] = org1[2] + width * right1[2];
8305         vert[ 3] = org1[0] - width * right1[0];
8306         vert[ 4] = org1[1] - width * right1[1];
8307         vert[ 5] = org1[2] - width * right1[2];
8308         vert[ 6] = org2[0] - width * right2[0];
8309         vert[ 7] = org2[1] - width * right2[1];
8310         vert[ 8] = org2[2] - width * right2[2];
8311         vert[ 9] = org2[0] + width * right2[0];
8312         vert[10] = org2[1] + width * right2[1];
8313         vert[11] = org2[2] + width * right2[2];
8314 }
8315
8316 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)
8317 {
8318         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8319         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8320         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8321         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8322         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8323         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8324         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8325         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8326         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8327         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8328         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8329         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8330 }
8331
8332 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8333 {
8334         int i;
8335         float *vertex3f;
8336         float v[3];
8337         VectorSet(v, x, y, z);
8338         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8339                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8340                         break;
8341         if (i == mesh->numvertices)
8342         {
8343                 if (mesh->numvertices < mesh->maxvertices)
8344                 {
8345                         VectorCopy(v, vertex3f);
8346                         mesh->numvertices++;
8347                 }
8348                 return mesh->numvertices;
8349         }
8350         else
8351                 return i;
8352 }
8353
8354 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8355 {
8356         int i;
8357         int *e, element[3];
8358         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8359         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8360         e = mesh->element3i + mesh->numtriangles * 3;
8361         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8362         {
8363                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8364                 if (mesh->numtriangles < mesh->maxtriangles)
8365                 {
8366                         *e++ = element[0];
8367                         *e++ = element[1];
8368                         *e++ = element[2];
8369                         mesh->numtriangles++;
8370                 }
8371                 element[1] = element[2];
8372         }
8373 }
8374
8375 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8376 {
8377         int i;
8378         int *e, element[3];
8379         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8380         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8381         e = mesh->element3i + mesh->numtriangles * 3;
8382         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8383         {
8384                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8385                 if (mesh->numtriangles < mesh->maxtriangles)
8386                 {
8387                         *e++ = element[0];
8388                         *e++ = element[1];
8389                         *e++ = element[2];
8390                         mesh->numtriangles++;
8391                 }
8392                 element[1] = element[2];
8393         }
8394 }
8395
8396 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8397 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8398 {
8399         int planenum, planenum2;
8400         int w;
8401         int tempnumpoints;
8402         mplane_t *plane, *plane2;
8403         double maxdist;
8404         double temppoints[2][256*3];
8405         // figure out how large a bounding box we need to properly compute this brush
8406         maxdist = 0;
8407         for (w = 0;w < numplanes;w++)
8408                 maxdist = max(maxdist, fabs(planes[w].dist));
8409         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8410         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8411         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8412         {
8413                 w = 0;
8414                 tempnumpoints = 4;
8415                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8416                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8417                 {
8418                         if (planenum2 == planenum)
8419                                 continue;
8420                         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);
8421                         w = !w;
8422                 }
8423                 if (tempnumpoints < 3)
8424                         continue;
8425                 // generate elements forming a triangle fan for this polygon
8426                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8427         }
8428 }
8429
8430 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)
8431 {
8432         texturelayer_t *layer;
8433         layer = t->currentlayers + t->currentnumlayers++;
8434         layer->type = type;
8435         layer->depthmask = depthmask;
8436         layer->blendfunc1 = blendfunc1;
8437         layer->blendfunc2 = blendfunc2;
8438         layer->texture = texture;
8439         layer->texmatrix = *matrix;
8440         layer->color[0] = r;
8441         layer->color[1] = g;
8442         layer->color[2] = b;
8443         layer->color[3] = a;
8444 }
8445
8446 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8447 {
8448         double index, f;
8449         index = parms[2] + r_refdef.scene.time * parms[3];
8450         index -= floor(index);
8451         switch (func)
8452         {
8453         default:
8454         case Q3WAVEFUNC_NONE:
8455         case Q3WAVEFUNC_NOISE:
8456         case Q3WAVEFUNC_COUNT:
8457                 f = 0;
8458                 break;
8459         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8460         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8461         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8462         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8463         case Q3WAVEFUNC_TRIANGLE:
8464                 index *= 4;
8465                 f = index - floor(index);
8466                 if (index < 1)
8467                         f = f;
8468                 else if (index < 2)
8469                         f = 1 - f;
8470                 else if (index < 3)
8471                         f = -f;
8472                 else
8473                         f = -(1 - f);
8474                 break;
8475         }
8476         return (float)(parms[0] + parms[1] * f);
8477 }
8478
8479 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8480 {
8481         int w, h, idx;
8482         float f;
8483         float tcmat[12];
8484         matrix4x4_t matrix, temp;
8485         switch(tcmod->tcmod)
8486         {
8487                 case Q3TCMOD_COUNT:
8488                 case Q3TCMOD_NONE:
8489                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8490                                 matrix = r_waterscrollmatrix;
8491                         else
8492                                 matrix = identitymatrix;
8493                         break;
8494                 case Q3TCMOD_ENTITYTRANSLATE:
8495                         // this is used in Q3 to allow the gamecode to control texcoord
8496                         // scrolling on the entity, which is not supported in darkplaces yet.
8497                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8498                         break;
8499                 case Q3TCMOD_ROTATE:
8500                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8501                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8502                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8503                         break;
8504                 case Q3TCMOD_SCALE:
8505                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8506                         break;
8507                 case Q3TCMOD_SCROLL:
8508                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8509                         break;
8510                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8511                         w = (int) tcmod->parms[0];
8512                         h = (int) tcmod->parms[1];
8513                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8514                         f = f - floor(f);
8515                         idx = (int) floor(f * w * h);
8516                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8517                         break;
8518                 case Q3TCMOD_STRETCH:
8519                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8520                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8521                         break;
8522                 case Q3TCMOD_TRANSFORM:
8523                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8524                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8525                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8526                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8527                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8528                         break;
8529                 case Q3TCMOD_TURBULENT:
8530                         // this is handled in the RSurf_PrepareVertices function
8531                         matrix = identitymatrix;
8532                         break;
8533         }
8534         temp = *texmatrix;
8535         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8536 }
8537
8538 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8539 {
8540         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8541         char name[MAX_QPATH];
8542         skinframe_t *skinframe;
8543         unsigned char pixels[296*194];
8544         strlcpy(cache->name, skinname, sizeof(cache->name));
8545         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8546         if (developer_loading.integer)
8547                 Con_Printf("loading %s\n", name);
8548         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8549         if (!skinframe || !skinframe->base)
8550         {
8551                 unsigned char *f;
8552                 fs_offset_t filesize;
8553                 skinframe = NULL;
8554                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8555                 if (f)
8556                 {
8557                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8558                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8559                         Mem_Free(f);
8560                 }
8561         }
8562         cache->skinframe = skinframe;
8563 }
8564
8565 texture_t *R_GetCurrentTexture(texture_t *t)
8566 {
8567         int i;
8568         const entity_render_t *ent = rsurface.entity;
8569         dp_model_t *model = ent->model;
8570         q3shaderinfo_layer_tcmod_t *tcmod;
8571
8572         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
8573                 return t->currentframe;
8574         t->update_lastrenderframe = r_frame;
8575         t->update_lastrenderentity = (void *)ent;
8576
8577         // switch to an alternate material if this is a q1bsp animated material
8578         {
8579                 texture_t *texture = t;
8580                 int s = rsurface.ent_skinnum;
8581                 if ((unsigned int)s >= (unsigned int)model->numskins)
8582                         s = 0;
8583                 if (model->skinscenes)
8584                 {
8585                         if (model->skinscenes[s].framecount > 1)
8586                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8587                         else
8588                                 s = model->skinscenes[s].firstframe;
8589                 }
8590                 if (s > 0)
8591                         t = t + s * model->num_surfaces;
8592                 if (t->animated)
8593                 {
8594                         // use an alternate animation if the entity's frame is not 0,
8595                         // and only if the texture has an alternate animation
8596                         if (rsurface.ent_alttextures && t->anim_total[1])
8597                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8598                         else
8599                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8600                 }
8601                 texture->currentframe = t;
8602         }
8603
8604         // update currentskinframe to be a qw skin or animation frame
8605         if (rsurface.ent_qwskin >= 0)
8606         {
8607                 i = rsurface.ent_qwskin;
8608                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8609                 {
8610                         r_qwskincache_size = cl.maxclients;
8611                         if (r_qwskincache)
8612                                 Mem_Free(r_qwskincache);
8613                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8614                 }
8615                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8616                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8617                 t->currentskinframe = r_qwskincache[i].skinframe;
8618                 if (t->currentskinframe == NULL)
8619                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8620         }
8621         else if (t->numskinframes >= 2)
8622                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8623         if (t->backgroundnumskinframes >= 2)
8624                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8625
8626         t->currentmaterialflags = t->basematerialflags;
8627         t->currentalpha = rsurface.colormod[3];
8628         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8629                 t->currentalpha *= r_wateralpha.value;
8630         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8631                 t->currentalpha *= t->r_water_wateralpha;
8632         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8633                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8634         if (!(rsurface.ent_flags & RENDER_LIGHT))
8635                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8636         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8637         {
8638                 // pick a model lighting mode
8639                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8640                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8641                 else
8642                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8643         }
8644         if (rsurface.ent_flags & RENDER_ADDITIVE)
8645                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8646         else if (t->currentalpha < 1)
8647                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8648         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8649                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8650         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8651                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8652         if (t->backgroundnumskinframes)
8653                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8654         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8655         {
8656                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8657                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8658         }
8659         else
8660                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8661         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8662                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8663
8664         // there is no tcmod
8665         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8666         {
8667                 t->currenttexmatrix = r_waterscrollmatrix;
8668                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8669         }
8670         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8671         {
8672                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8673                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8674         }
8675
8676         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8677                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8678         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8679                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8680
8681         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8682         if (t->currentskinframe->qpixels)
8683                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8684         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8685         if (!t->basetexture)
8686                 t->basetexture = r_texture_notexture;
8687         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8688         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8689         t->nmaptexture = t->currentskinframe->nmap;
8690         if (!t->nmaptexture)
8691                 t->nmaptexture = r_texture_blanknormalmap;
8692         t->glosstexture = r_texture_black;
8693         t->glowtexture = t->currentskinframe->glow;
8694         t->fogtexture = t->currentskinframe->fog;
8695         if (t->backgroundnumskinframes)
8696         {
8697                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8698                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8699                 t->backgroundglosstexture = r_texture_black;
8700                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8701                 if (!t->backgroundnmaptexture)
8702                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8703         }
8704         else
8705         {
8706                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8707                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8708                 t->backgroundglosstexture = r_texture_black;
8709                 t->backgroundglowtexture = NULL;
8710         }
8711         t->specularpower = r_shadow_glossexponent.value;
8712         // TODO: store reference values for these in the texture?
8713         t->specularscale = 0;
8714         if (r_shadow_gloss.integer > 0)
8715         {
8716                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8717                 {
8718                         if (r_shadow_glossintensity.value > 0)
8719                         {
8720                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8721                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8722                                 t->specularscale = r_shadow_glossintensity.value;
8723                         }
8724                 }
8725                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8726                 {
8727                         t->glosstexture = r_texture_white;
8728                         t->backgroundglosstexture = r_texture_white;
8729                         t->specularscale = r_shadow_gloss2intensity.value;
8730                         t->specularpower = r_shadow_gloss2exponent.value;
8731                 }
8732         }
8733         t->specularscale *= t->specularscalemod;
8734         t->specularpower *= t->specularpowermod;
8735
8736         // lightmaps mode looks bad with dlights using actual texturing, so turn
8737         // off the colormap and glossmap, but leave the normalmap on as it still
8738         // accurately represents the shading involved
8739         if (gl_lightmaps.integer)
8740         {
8741                 t->basetexture = r_texture_grey128;
8742                 t->pantstexture = r_texture_black;
8743                 t->shirttexture = r_texture_black;
8744                 t->nmaptexture = r_texture_blanknormalmap;
8745                 t->glosstexture = r_texture_black;
8746                 t->glowtexture = NULL;
8747                 t->fogtexture = NULL;
8748                 t->backgroundbasetexture = NULL;
8749                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8750                 t->backgroundglosstexture = r_texture_black;
8751                 t->backgroundglowtexture = NULL;
8752                 t->specularscale = 0;
8753                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8754         }
8755
8756         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8757         VectorClear(t->dlightcolor);
8758         t->currentnumlayers = 0;
8759         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8760         {
8761                 int blendfunc1, blendfunc2;
8762                 qboolean depthmask;
8763                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8764                 {
8765                         blendfunc1 = GL_SRC_ALPHA;
8766                         blendfunc2 = GL_ONE;
8767                 }
8768                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8769                 {
8770                         blendfunc1 = GL_SRC_ALPHA;
8771                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8772                 }
8773                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8774                 {
8775                         blendfunc1 = t->customblendfunc[0];
8776                         blendfunc2 = t->customblendfunc[1];
8777                 }
8778                 else
8779                 {
8780                         blendfunc1 = GL_ONE;
8781                         blendfunc2 = GL_ZERO;
8782                 }
8783                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8784                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8785                 {
8786                         // fullbright is not affected by r_refdef.lightmapintensity
8787                         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]);
8788                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8789                                 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]);
8790                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8791                                 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]);
8792                 }
8793                 else
8794                 {
8795                         vec3_t ambientcolor;
8796                         float colorscale;
8797                         // set the color tint used for lights affecting this surface
8798                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8799                         colorscale = 2;
8800                         // q3bsp has no lightmap updates, so the lightstylevalue that
8801                         // would normally be baked into the lightmap must be
8802                         // applied to the color
8803                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8804                         if (model->type == mod_brushq3)
8805                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8806                         colorscale *= r_refdef.lightmapintensity;
8807                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8808                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8809                         // basic lit geometry
8810                         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]);
8811                         // add pants/shirt if needed
8812                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8813                                 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]);
8814                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8815                                 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]);
8816                         // now add ambient passes if needed
8817                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8818                         {
8819                                 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]);
8820                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8821                                         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]);
8822                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8823                                         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]);
8824                         }
8825                 }
8826                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8827                         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]);
8828                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8829                 {
8830                         // if this is opaque use alpha blend which will darken the earlier
8831                         // passes cheaply.
8832                         //
8833                         // if this is an alpha blended material, all the earlier passes
8834                         // were darkened by fog already, so we only need to add the fog
8835                         // color ontop through the fog mask texture
8836                         //
8837                         // if this is an additive blended material, all the earlier passes
8838                         // were darkened by fog already, and we should not add fog color
8839                         // (because the background was not darkened, there is no fog color
8840                         // that was lost behind it).
8841                         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]);
8842                 }
8843         }
8844
8845         return t->currentframe;
8846 }
8847
8848 rsurfacestate_t rsurface;
8849
8850 void R_Mesh_ResizeArrays(int newvertices)
8851 {
8852         float *base;
8853         if (rsurface.array_size >= newvertices)
8854                 return;
8855         if (rsurface.array_modelvertex3f)
8856                 Mem_Free(rsurface.array_modelvertex3f);
8857         rsurface.array_size = (newvertices + 1023) & ~1023;
8858         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8859         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8860         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8861         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8862         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8863         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8864         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8865         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8866         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8867         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8868         rsurface.array_color4f           = base + rsurface.array_size * 27;
8869         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8870 }
8871
8872 void RSurf_ActiveWorldEntity(void)
8873 {
8874         dp_model_t *model = r_refdef.scene.worldmodel;
8875         //if (rsurface.entity == r_refdef.scene.worldentity)
8876         //      return;
8877         rsurface.entity = r_refdef.scene.worldentity;
8878         rsurface.skeleton = NULL;
8879         rsurface.ent_skinnum = 0;
8880         rsurface.ent_qwskin = -1;
8881         rsurface.ent_shadertime = 0;
8882         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8883         if (rsurface.array_size < model->surfmesh.num_vertices)
8884                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8885         rsurface.matrix = identitymatrix;
8886         rsurface.inversematrix = identitymatrix;
8887         rsurface.matrixscale = 1;
8888         rsurface.inversematrixscale = 1;
8889         R_EntityMatrix(&identitymatrix);
8890         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8891         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8892         rsurface.fograngerecip = r_refdef.fograngerecip;
8893         rsurface.fogheightfade = r_refdef.fogheightfade;
8894         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8895         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8896         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8897         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8898         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8899         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8900         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8901         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8902         rsurface.colormod[3] = 1;
8903         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);
8904         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8905         rsurface.frameblend[0].lerp = 1;
8906         rsurface.ent_alttextures = false;
8907         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8908         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8909         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8910         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8911         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8912         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8913         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8914         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8915         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8916         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8917         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8918         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8919         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8920         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8921         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8922         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8923         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8924         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8925         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8926         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8927         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8928         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8929         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8930         rsurface.modelelement3i = model->surfmesh.data_element3i;
8931         rsurface.modelelement3s = model->surfmesh.data_element3s;
8932         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8933         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8934         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8935         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8936         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8937         rsurface.modelsurfaces = model->data_surfaces;
8938         rsurface.generatedvertex = false;
8939         rsurface.vertex3f  = rsurface.modelvertex3f;
8940         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8941         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8942         rsurface.svector3f = rsurface.modelsvector3f;
8943         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8944         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8945         rsurface.tvector3f = rsurface.modeltvector3f;
8946         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8947         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8948         rsurface.normal3f  = rsurface.modelnormal3f;
8949         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8950         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8951         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8952 }
8953
8954 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8955 {
8956         dp_model_t *model = ent->model;
8957         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8958         //      return;
8959         rsurface.entity = (entity_render_t *)ent;
8960         rsurface.skeleton = ent->skeleton;
8961         rsurface.ent_skinnum = ent->skinnum;
8962         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;
8963         rsurface.ent_shadertime = ent->shadertime;
8964         rsurface.ent_flags = ent->flags;
8965         if (rsurface.array_size < model->surfmesh.num_vertices)
8966                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8967         rsurface.matrix = ent->matrix;
8968         rsurface.inversematrix = ent->inversematrix;
8969         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8970         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8971         R_EntityMatrix(&rsurface.matrix);
8972         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8973         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8974         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8975         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8976         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8977         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8978         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8979         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8980         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8981         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8982         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8983         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8984         rsurface.colormod[3] = ent->alpha;
8985         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8986         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8987         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8988         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8989         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8990         if (ent->model->brush.submodel && !prepass)
8991         {
8992                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8993                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8994         }
8995         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8996         {
8997                 if (ent->animcache_vertex3f && !r_framedata_failed)
8998                 {
8999                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9000                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9001                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9002                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9003                 }
9004                 else if (wanttangents)
9005                 {
9006                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9007                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9008                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9009                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9010                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9011                 }
9012                 else if (wantnormals)
9013                 {
9014                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9015                         rsurface.modelsvector3f = NULL;
9016                         rsurface.modeltvector3f = NULL;
9017                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9018                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9019                 }
9020                 else
9021                 {
9022                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9023                         rsurface.modelsvector3f = NULL;
9024                         rsurface.modeltvector3f = NULL;
9025                         rsurface.modelnormal3f = NULL;
9026                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9027                 }
9028                 rsurface.modelvertex3f_bufferobject = 0;
9029                 rsurface.modelvertex3f_bufferoffset = 0;
9030                 rsurface.modelsvector3f_bufferobject = 0;
9031                 rsurface.modelsvector3f_bufferoffset = 0;
9032                 rsurface.modeltvector3f_bufferobject = 0;
9033                 rsurface.modeltvector3f_bufferoffset = 0;
9034                 rsurface.modelnormal3f_bufferobject = 0;
9035                 rsurface.modelnormal3f_bufferoffset = 0;
9036                 rsurface.generatedvertex = true;
9037         }
9038         else
9039         {
9040                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9041                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9042                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9043                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9044                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9045                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9046                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9047                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9048                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9049                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9050                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9051                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9052                 rsurface.generatedvertex = false;
9053         }
9054         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9055         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9056         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9057         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9058         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9059         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9060         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9061         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9062         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9063         rsurface.modelelement3i = model->surfmesh.data_element3i;
9064         rsurface.modelelement3s = model->surfmesh.data_element3s;
9065         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9066         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9067         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9068         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9069         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9070         rsurface.modelsurfaces = model->data_surfaces;
9071         rsurface.vertex3f  = rsurface.modelvertex3f;
9072         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9073         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9074         rsurface.svector3f = rsurface.modelsvector3f;
9075         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9076         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9077         rsurface.tvector3f = rsurface.modeltvector3f;
9078         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9079         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9080         rsurface.normal3f  = rsurface.modelnormal3f;
9081         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9082         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9083         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9084 }
9085
9086 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)
9087 {
9088         rsurface.entity = r_refdef.scene.worldentity;
9089         rsurface.skeleton = NULL;
9090         rsurface.ent_skinnum = 0;
9091         rsurface.ent_qwskin = -1;
9092         rsurface.ent_shadertime = shadertime;
9093         rsurface.ent_flags = entflags;
9094         rsurface.modelnum_vertices = numvertices;
9095         rsurface.modelnum_triangles = numtriangles;
9096         if (rsurface.array_size < rsurface.modelnum_vertices)
9097                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9098         rsurface.matrix = *matrix;
9099         rsurface.inversematrix = *inversematrix;
9100         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9101         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9102         R_EntityMatrix(&rsurface.matrix);
9103         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9104         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9105         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9106         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9107         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9108         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9109         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9110         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9111         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9112         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9113         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9114         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9115         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);
9116         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9117         rsurface.frameblend[0].lerp = 1;
9118         rsurface.ent_alttextures = false;
9119         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9120         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9121         if (wanttangents)
9122         {
9123                 rsurface.modelvertex3f = vertex3f;
9124                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9125                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9126                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9127         }
9128         else if (wantnormals)
9129         {
9130                 rsurface.modelvertex3f = vertex3f;
9131                 rsurface.modelsvector3f = NULL;
9132                 rsurface.modeltvector3f = NULL;
9133                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9134         }
9135         else
9136         {
9137                 rsurface.modelvertex3f = vertex3f;
9138                 rsurface.modelsvector3f = NULL;
9139                 rsurface.modeltvector3f = NULL;
9140                 rsurface.modelnormal3f = NULL;
9141         }
9142         rsurface.modelvertex3f_bufferobject = 0;
9143         rsurface.modelvertex3f_bufferoffset = 0;
9144         rsurface.modelsvector3f_bufferobject = 0;
9145         rsurface.modelsvector3f_bufferoffset = 0;
9146         rsurface.modeltvector3f_bufferobject = 0;
9147         rsurface.modeltvector3f_bufferoffset = 0;
9148         rsurface.modelnormal3f_bufferobject = 0;
9149         rsurface.modelnormal3f_bufferoffset = 0;
9150         rsurface.generatedvertex = true;
9151         rsurface.modellightmapcolor4f  = color4f;
9152         rsurface.modellightmapcolor4f_bufferobject = 0;
9153         rsurface.modellightmapcolor4f_bufferoffset = 0;
9154         rsurface.modeltexcoordtexture2f  = texcoord2f;
9155         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9156         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9157         rsurface.modeltexcoordlightmap2f  = NULL;
9158         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9159         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9160         rsurface.modelelement3i = element3i;
9161         rsurface.modelelement3s = element3s;
9162         rsurface.modelelement3i_bufferobject = 0;
9163         rsurface.modelelement3s_bufferobject = 0;
9164         rsurface.modellightmapoffsets = NULL;
9165         rsurface.modelsurfaces = NULL;
9166         rsurface.vertex3f  = rsurface.modelvertex3f;
9167         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9168         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9169         rsurface.svector3f = rsurface.modelsvector3f;
9170         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9171         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9172         rsurface.tvector3f = rsurface.modeltvector3f;
9173         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9174         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9175         rsurface.normal3f  = rsurface.modelnormal3f;
9176         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9177         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9178         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9179
9180         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9181         {
9182                 if ((wantnormals || wanttangents) && !normal3f)
9183                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9184                 if (wanttangents && !svector3f)
9185                         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);
9186         }
9187 }
9188
9189 float RSurf_FogPoint(const float *v)
9190 {
9191         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9192         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9193         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9194         float FogHeightFade = r_refdef.fogheightfade;
9195         float fogfrac;
9196         unsigned int fogmasktableindex;
9197         if (r_refdef.fogplaneviewabove)
9198                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9199         else
9200                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9201         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9202         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9203 }
9204
9205 float RSurf_FogVertex(const float *v)
9206 {
9207         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9208         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9209         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9210         float FogHeightFade = rsurface.fogheightfade;
9211         float fogfrac;
9212         unsigned int fogmasktableindex;
9213         if (r_refdef.fogplaneviewabove)
9214                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9215         else
9216                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9217         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9218         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9219 }
9220
9221 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9222 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9223 {
9224         int deformindex;
9225         int texturesurfaceindex;
9226         int i, j;
9227         float amplitude;
9228         float animpos;
9229         float scale;
9230         const float *v1, *in_tc;
9231         float *out_tc;
9232         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9233         float waveparms[4];
9234         q3shaderinfo_deform_t *deform;
9235         // 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
9236         if (rsurface.generatedvertex)
9237         {
9238                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9239                         generatenormals = true;
9240                 for (i = 0;i < Q3MAXDEFORMS;i++)
9241                 {
9242                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9243                         {
9244                                 generatetangents = true;
9245                                 generatenormals = true;
9246                         }
9247                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9248                                 generatenormals = true;
9249                 }
9250                 if (generatenormals && !rsurface.modelnormal3f)
9251                 {
9252                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9253                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9254                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9255                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9256                 }
9257                 if (generatetangents && !rsurface.modelsvector3f)
9258                 {
9259                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9260                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9261                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9262                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9263                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9264                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9265                         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);
9266                 }
9267         }
9268         rsurface.vertex3f  = rsurface.modelvertex3f;
9269         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9270         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9271         rsurface.svector3f = rsurface.modelsvector3f;
9272         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9273         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9274         rsurface.tvector3f = rsurface.modeltvector3f;
9275         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9276         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9277         rsurface.normal3f  = rsurface.modelnormal3f;
9278         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9279         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9280         // if vertices are deformed (sprite flares and things in maps, possibly
9281         // water waves, bulges and other deformations), generate them into
9282         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9283         // (may be static model data or generated data for an animated model, or
9284         //  the previous deform pass)
9285         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9286         {
9287                 switch (deform->deform)
9288                 {
9289                 default:
9290                 case Q3DEFORM_PROJECTIONSHADOW:
9291                 case Q3DEFORM_TEXT0:
9292                 case Q3DEFORM_TEXT1:
9293                 case Q3DEFORM_TEXT2:
9294                 case Q3DEFORM_TEXT3:
9295                 case Q3DEFORM_TEXT4:
9296                 case Q3DEFORM_TEXT5:
9297                 case Q3DEFORM_TEXT6:
9298                 case Q3DEFORM_TEXT7:
9299                 case Q3DEFORM_NONE:
9300                         break;
9301                 case Q3DEFORM_AUTOSPRITE:
9302                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9303                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9304                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9305                         VectorNormalize(newforward);
9306                         VectorNormalize(newright);
9307                         VectorNormalize(newup);
9308                         // make deformed versions of only the model vertices used by the specified surfaces
9309                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9310                         {
9311                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9312                                 // a single autosprite surface can contain multiple sprites...
9313                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9314                                 {
9315                                         VectorClear(center);
9316                                         for (i = 0;i < 4;i++)
9317                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9318                                         VectorScale(center, 0.25f, center);
9319                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9320                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9321                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9322                                         for (i = 0;i < 4;i++)
9323                                         {
9324                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9325                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9326                                         }
9327                                 }
9328                                 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);
9329                                 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);
9330                         }
9331                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9332                         rsurface.vertex3f_bufferobject = 0;
9333                         rsurface.vertex3f_bufferoffset = 0;
9334                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9335                         rsurface.svector3f_bufferobject = 0;
9336                         rsurface.svector3f_bufferoffset = 0;
9337                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9338                         rsurface.tvector3f_bufferobject = 0;
9339                         rsurface.tvector3f_bufferoffset = 0;
9340                         rsurface.normal3f = rsurface.array_deformednormal3f;
9341                         rsurface.normal3f_bufferobject = 0;
9342                         rsurface.normal3f_bufferoffset = 0;
9343                         break;
9344                 case Q3DEFORM_AUTOSPRITE2:
9345                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9346                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9347                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9348                         VectorNormalize(newforward);
9349                         VectorNormalize(newright);
9350                         VectorNormalize(newup);
9351                         // make deformed versions of only the model vertices used by the specified surfaces
9352                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9353                         {
9354                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9355                                 const float *v1, *v2;
9356                                 vec3_t start, end;
9357                                 float f, l;
9358                                 struct
9359                                 {
9360                                         float length2;
9361                                         const float *v1;
9362                                         const float *v2;
9363                                 }
9364                                 shortest[2];
9365                                 memset(shortest, 0, sizeof(shortest));
9366                                 // a single autosprite surface can contain multiple sprites...
9367                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9368                                 {
9369                                         VectorClear(center);
9370                                         for (i = 0;i < 4;i++)
9371                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9372                                         VectorScale(center, 0.25f, center);
9373                                         // find the two shortest edges, then use them to define the
9374                                         // axis vectors for rotating around the central axis
9375                                         for (i = 0;i < 6;i++)
9376                                         {
9377                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9378                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9379 #if 0
9380                                                 Debug_PolygonBegin(NULL, 0);
9381                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9382                                                 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);
9383                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9384                                                 Debug_PolygonEnd();
9385 #endif
9386                                                 l = VectorDistance2(v1, v2);
9387                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9388                                                 if (v1[2] != v2[2])
9389                                                         l += (1.0f / 1024.0f);
9390                                                 if (shortest[0].length2 > l || i == 0)
9391                                                 {
9392                                                         shortest[1] = shortest[0];
9393                                                         shortest[0].length2 = l;
9394                                                         shortest[0].v1 = v1;
9395                                                         shortest[0].v2 = v2;
9396                                                 }
9397                                                 else if (shortest[1].length2 > l || i == 1)
9398                                                 {
9399                                                         shortest[1].length2 = l;
9400                                                         shortest[1].v1 = v1;
9401                                                         shortest[1].v2 = v2;
9402                                                 }
9403                                         }
9404                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9405                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9406 #if 0
9407                                         Debug_PolygonBegin(NULL, 0);
9408                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9409                                         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);
9410                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9411                                         Debug_PolygonEnd();
9412 #endif
9413                                         // this calculates the right vector from the shortest edge
9414                                         // and the up vector from the edge midpoints
9415                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9416                                         VectorNormalize(right);
9417                                         VectorSubtract(end, start, up);
9418                                         VectorNormalize(up);
9419                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9420                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9421                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9422                                         VectorNegate(forward, forward);
9423                                         VectorReflect(forward, 0, up, forward);
9424                                         VectorNormalize(forward);
9425                                         CrossProduct(up, forward, newright);
9426                                         VectorNormalize(newright);
9427 #if 0
9428                                         Debug_PolygonBegin(NULL, 0);
9429                                         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);
9430                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9431                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9432                                         Debug_PolygonEnd();
9433 #endif
9434 #if 0
9435                                         Debug_PolygonBegin(NULL, 0);
9436                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9437                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9438                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9439                                         Debug_PolygonEnd();
9440 #endif
9441                                         // rotate the quad around the up axis vector, this is made
9442                                         // especially easy by the fact we know the quad is flat,
9443                                         // so we only have to subtract the center position and
9444                                         // measure distance along the right vector, and then
9445                                         // multiply that by the newright vector and add back the
9446                                         // center position
9447                                         // we also need to subtract the old position to undo the
9448                                         // displacement from the center, which we do with a
9449                                         // DotProduct, the subtraction/addition of center is also
9450                                         // optimized into DotProducts here
9451                                         l = DotProduct(right, center);
9452                                         for (i = 0;i < 4;i++)
9453                                         {
9454                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9455                                                 f = DotProduct(right, v1) - l;
9456                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9457                                         }
9458                                 }
9459                                 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);
9460                                 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);
9461                         }
9462                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9463                         rsurface.vertex3f_bufferobject = 0;
9464                         rsurface.vertex3f_bufferoffset = 0;
9465                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9466                         rsurface.svector3f_bufferobject = 0;
9467                         rsurface.svector3f_bufferoffset = 0;
9468                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9469                         rsurface.tvector3f_bufferobject = 0;
9470                         rsurface.tvector3f_bufferoffset = 0;
9471                         rsurface.normal3f = rsurface.array_deformednormal3f;
9472                         rsurface.normal3f_bufferobject = 0;
9473                         rsurface.normal3f_bufferoffset = 0;
9474                         break;
9475                 case Q3DEFORM_NORMAL:
9476                         // deform the normals to make reflections wavey
9477                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9478                         {
9479                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9480                                 for (j = 0;j < surface->num_vertices;j++)
9481                                 {
9482                                         float vertex[3];
9483                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9484                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9485                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9486                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9487                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9488                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9489                                         VectorNormalize(normal);
9490                                 }
9491                                 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);
9492                         }
9493                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9494                         rsurface.svector3f_bufferobject = 0;
9495                         rsurface.svector3f_bufferoffset = 0;
9496                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9497                         rsurface.tvector3f_bufferobject = 0;
9498                         rsurface.tvector3f_bufferoffset = 0;
9499                         rsurface.normal3f = rsurface.array_deformednormal3f;
9500                         rsurface.normal3f_bufferobject = 0;
9501                         rsurface.normal3f_bufferoffset = 0;
9502                         break;
9503                 case Q3DEFORM_WAVE:
9504                         // deform vertex array to make wavey water and flags and such
9505                         waveparms[0] = deform->waveparms[0];
9506                         waveparms[1] = deform->waveparms[1];
9507                         waveparms[2] = deform->waveparms[2];
9508                         waveparms[3] = deform->waveparms[3];
9509                         // this is how a divisor of vertex influence on deformation
9510                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9511                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9512                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9513                         {
9514                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9515                                 for (j = 0;j < surface->num_vertices;j++)
9516                                 {
9517                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9518                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9519                                         // if the wavefunc depends on time, evaluate it per-vertex
9520                                         if (waveparms[3])
9521                                         {
9522                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9523                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9524                                         }
9525                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9526                                 }
9527                         }
9528                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9529                         rsurface.vertex3f_bufferobject = 0;
9530                         rsurface.vertex3f_bufferoffset = 0;
9531                         break;
9532                 case Q3DEFORM_BULGE:
9533                         // deform vertex array to make the surface have moving bulges
9534                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9535                         {
9536                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9537                                 for (j = 0;j < surface->num_vertices;j++)
9538                                 {
9539                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9540                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9541                                 }
9542                         }
9543                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9544                         rsurface.vertex3f_bufferobject = 0;
9545                         rsurface.vertex3f_bufferoffset = 0;
9546                         break;
9547                 case Q3DEFORM_MOVE:
9548                         // deform vertex array
9549                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9550                         VectorScale(deform->parms, scale, waveparms);
9551                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9552                         {
9553                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9554                                 for (j = 0;j < surface->num_vertices;j++)
9555                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9556                         }
9557                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9558                         rsurface.vertex3f_bufferobject = 0;
9559                         rsurface.vertex3f_bufferoffset = 0;
9560                         break;
9561                 }
9562         }
9563         // generate texcoords based on the chosen texcoord source
9564         switch(rsurface.texture->tcgen.tcgen)
9565         {
9566         default:
9567         case Q3TCGEN_TEXTURE:
9568                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9569                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9570                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9571                 break;
9572         case Q3TCGEN_LIGHTMAP:
9573                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9574                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9575                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9576                 break;
9577         case Q3TCGEN_VECTOR:
9578                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9579                 {
9580                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9581                         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)
9582                         {
9583                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9584                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9585                         }
9586                 }
9587                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9588                 rsurface.texcoordtexture2f_bufferobject  = 0;
9589                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9590                 break;
9591         case Q3TCGEN_ENVIRONMENT:
9592                 // make environment reflections using a spheremap
9593                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9594                 {
9595                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9596                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9597                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9598                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9599                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9600                         {
9601                                 // identical to Q3A's method, but executed in worldspace so
9602                                 // carried models can be shiny too
9603
9604                                 float viewer[3], d, reflected[3], worldreflected[3];
9605
9606                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9607                                 // VectorNormalize(viewer);
9608
9609                                 d = DotProduct(normal, viewer);
9610
9611                                 reflected[0] = normal[0]*2*d - viewer[0];
9612                                 reflected[1] = normal[1]*2*d - viewer[1];
9613                                 reflected[2] = normal[2]*2*d - viewer[2];
9614                                 // note: this is proportinal to viewer, so we can normalize later
9615
9616                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9617                                 VectorNormalize(worldreflected);
9618
9619                                 // note: this sphere map only uses world x and z!
9620                                 // so positive and negative y will LOOK THE SAME.
9621                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9622                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9623                         }
9624                 }
9625                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9626                 rsurface.texcoordtexture2f_bufferobject  = 0;
9627                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9628                 break;
9629         }
9630         // the only tcmod that needs software vertex processing is turbulent, so
9631         // check for it here and apply the changes if needed
9632         // and we only support that as the first one
9633         // (handling a mixture of turbulent and other tcmods would be problematic
9634         //  without punting it entirely to a software path)
9635         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9636         {
9637                 amplitude = rsurface.texture->tcmods[0].parms[1];
9638                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9639                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9640                 {
9641                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9642                         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)
9643                         {
9644                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9645                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9646                         }
9647                 }
9648                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9649                 rsurface.texcoordtexture2f_bufferobject  = 0;
9650                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9651         }
9652         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9653         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9654         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9655         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9656 }
9657
9658 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9659 {
9660         int i, j;
9661         const msurface_t *surface = texturesurfacelist[0];
9662         const msurface_t *surface2;
9663         int firstvertex;
9664         int endvertex;
9665         int numvertices;
9666         int numtriangles;
9667         // TODO: lock all array ranges before render, rather than on each surface
9668         if (texturenumsurfaces == 1)
9669         {
9670                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9671                 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);
9672         }
9673         else if (r_batchmode.integer == 2)
9674         {
9675                 #define MAXBATCHTRIANGLES 4096
9676                 int batchtriangles = 0;
9677                 static int batchelements[MAXBATCHTRIANGLES*3];
9678                 for (i = 0;i < texturenumsurfaces;i = j)
9679                 {
9680                         surface = texturesurfacelist[i];
9681                         j = i + 1;
9682                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9683                         {
9684                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9685                                 continue;
9686                         }
9687                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9688                         batchtriangles = surface->num_triangles;
9689                         firstvertex = surface->num_firstvertex;
9690                         endvertex = surface->num_firstvertex + surface->num_vertices;
9691                         for (;j < texturenumsurfaces;j++)
9692                         {
9693                                 surface2 = texturesurfacelist[j];
9694                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9695                                         break;
9696                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9697                                 batchtriangles += surface2->num_triangles;
9698                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9699                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9700                         }
9701                         surface2 = texturesurfacelist[j-1];
9702                         numvertices = endvertex - firstvertex;
9703                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9704                 }
9705         }
9706         else if (r_batchmode.integer == 1)
9707         {
9708                 for (i = 0;i < texturenumsurfaces;i = j)
9709                 {
9710                         surface = texturesurfacelist[i];
9711                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9712                                 if (texturesurfacelist[j] != surface2)
9713                                         break;
9714                         surface2 = texturesurfacelist[j-1];
9715                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9716                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9717                         GL_LockArrays(surface->num_firstvertex, numvertices);
9718                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9719                 }
9720         }
9721         else
9722         {
9723                 for (i = 0;i < texturenumsurfaces;i++)
9724                 {
9725                         surface = texturesurfacelist[i];
9726                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9727                         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);
9728                 }
9729         }
9730 }
9731
9732 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9733 {
9734         switch(vid.renderpath)
9735         {
9736         case RENDERPATH_CGGL:
9737 #ifdef SUPPORTCG
9738                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9739                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9740 #endif
9741                 break;
9742         case RENDERPATH_GL20:
9743                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9744                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9745                 break;
9746         case RENDERPATH_GL13:
9747         case RENDERPATH_GL11:
9748                 R_Mesh_TexBind(0, surface->lightmaptexture);
9749                 break;
9750         }
9751 }
9752
9753 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9754 {
9755         // pick the closest matching water plane and bind textures
9756         int planeindex, vertexindex;
9757         float d, bestd;
9758         vec3_t vert;
9759         const float *v;
9760         r_waterstate_waterplane_t *p, *bestp;
9761         bestd = 0;
9762         bestp = NULL;
9763         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9764         {
9765                 d = 0;
9766                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9767                 {
9768                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9769                         d += fabs(PlaneDiff(vert, &p->plane));
9770                 }
9771                 if (bestd > d || !bestp)
9772                 {
9773                         bestd = d;
9774                         bestp = p;
9775                 }
9776         }
9777         switch(vid.renderpath)
9778         {
9779         case RENDERPATH_CGGL:
9780 #ifdef SUPPORTCG
9781                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9782                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9783 #endif
9784                 break;
9785         case RENDERPATH_GL20:
9786                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9787                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9788                 break;
9789         case RENDERPATH_GL13:
9790         case RENDERPATH_GL11:
9791                 break;
9792         }
9793 }
9794
9795 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9796 {
9797         int i;
9798         const msurface_t *surface;
9799         if (r_waterstate.renderingscene)
9800                 return;
9801         for (i = 0;i < texturenumsurfaces;i++)
9802         {
9803                 surface = texturesurfacelist[i];
9804                 RSurf_BindLightmapForSurface(surface);
9805                 RSurf_BindReflectionForSurface(surface);
9806                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9807                 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);
9808         }
9809 }
9810
9811 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9812 {
9813         int i;
9814         int j;
9815         const msurface_t *surface = texturesurfacelist[0];
9816         const msurface_t *surface2;
9817         int firstvertex;
9818         int endvertex;
9819         int numvertices;
9820         int numtriangles;
9821         if (texturenumsurfaces == 1)
9822         {
9823                 RSurf_BindLightmapForSurface(surface);
9824                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9825                 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);
9826         }
9827         else if (r_batchmode.integer == 2)
9828         {
9829 #define MAXBATCHTRIANGLES 4096
9830                 int batchtriangles = 0;
9831                 static int batchelements[MAXBATCHTRIANGLES*3];
9832                 for (i = 0;i < texturenumsurfaces;i = j)
9833                 {
9834                         surface = texturesurfacelist[i];
9835                         RSurf_BindLightmapForSurface(surface);
9836                         j = i + 1;
9837                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9838                         {
9839                                 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);
9840                                 continue;
9841                         }
9842                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9843                         batchtriangles = surface->num_triangles;
9844                         firstvertex = surface->num_firstvertex;
9845                         endvertex = surface->num_firstvertex + surface->num_vertices;
9846                         for (;j < texturenumsurfaces;j++)
9847                         {
9848                                 surface2 = texturesurfacelist[j];
9849                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9850                                         break;
9851                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9852                                 batchtriangles += surface2->num_triangles;
9853                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9854                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9855                         }
9856                         surface2 = texturesurfacelist[j-1];
9857                         numvertices = endvertex - firstvertex;
9858                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9859                 }
9860         }
9861         else if (r_batchmode.integer == 1)
9862         {
9863 #if 0
9864                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9865                 for (i = 0;i < texturenumsurfaces;i = j)
9866                 {
9867                         surface = texturesurfacelist[i];
9868                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9869                                 if (texturesurfacelist[j] != surface2)
9870                                         break;
9871                         Con_Printf(" %i", j - i);
9872                 }
9873                 Con_Printf("\n");
9874                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9875 #endif
9876                 for (i = 0;i < texturenumsurfaces;i = j)
9877                 {
9878                         surface = texturesurfacelist[i];
9879                         RSurf_BindLightmapForSurface(surface);
9880                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9881                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9882                                         break;
9883 #if 0
9884                         Con_Printf(" %i", j - i);
9885 #endif
9886                         surface2 = texturesurfacelist[j-1];
9887                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9888                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9889                         GL_LockArrays(surface->num_firstvertex, numvertices);
9890                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9891                 }
9892 #if 0
9893                 Con_Printf("\n");
9894 #endif
9895         }
9896         else
9897         {
9898                 for (i = 0;i < texturenumsurfaces;i++)
9899                 {
9900                         surface = texturesurfacelist[i];
9901                         RSurf_BindLightmapForSurface(surface);
9902                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9903                         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);
9904                 }
9905         }
9906 }
9907
9908 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9909 {
9910         int j;
9911         int texturesurfaceindex;
9912         if (r_showsurfaces.integer == 2)
9913         {
9914                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9915                 {
9916                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9917                         for (j = 0;j < surface->num_triangles;j++)
9918                         {
9919                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9920                                 GL_Color(f, f, f, 1);
9921                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9922                         }
9923                 }
9924         }
9925         else
9926         {
9927                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9928                 {
9929                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9930                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9931                         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);
9932                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9933                         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);
9934                 }
9935         }
9936 }
9937
9938 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9939 {
9940         int texturesurfaceindex;
9941         int i;
9942         const float *v;
9943         float *c2;
9944         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9945         {
9946                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9947                 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)
9948                 {
9949                         c2[0] = 0.5;
9950                         c2[1] = 0.5;
9951                         c2[2] = 0.5;
9952                         c2[3] = 1;
9953                 }
9954         }
9955         rsurface.lightmapcolor4f = rsurface.array_color4f;
9956         rsurface.lightmapcolor4f_bufferobject = 0;
9957         rsurface.lightmapcolor4f_bufferoffset = 0;
9958 }
9959
9960 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9961 {
9962         int texturesurfaceindex;
9963         int i;
9964         float f;
9965         const float *v;
9966         const float *c;
9967         float *c2;
9968         if (rsurface.lightmapcolor4f)
9969         {
9970                 // generate color arrays for the surfaces in this list
9971                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9972                 {
9973                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9974                         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)
9975                         {
9976                                 f = RSurf_FogVertex(v);
9977                                 c2[0] = c[0] * f;
9978                                 c2[1] = c[1] * f;
9979                                 c2[2] = c[2] * f;
9980                                 c2[3] = c[3];
9981                         }
9982                 }
9983         }
9984         else
9985         {
9986                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9987                 {
9988                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9989                         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)
9990                         {
9991                                 f = RSurf_FogVertex(v);
9992                                 c2[0] = f;
9993                                 c2[1] = f;
9994                                 c2[2] = f;
9995                                 c2[3] = 1;
9996                         }
9997                 }
9998         }
9999         rsurface.lightmapcolor4f = rsurface.array_color4f;
10000         rsurface.lightmapcolor4f_bufferobject = 0;
10001         rsurface.lightmapcolor4f_bufferoffset = 0;
10002 }
10003
10004 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10005 {
10006         int texturesurfaceindex;
10007         int i;
10008         float f;
10009         const float *v;
10010         const float *c;
10011         float *c2;
10012         if (!rsurface.lightmapcolor4f)
10013                 return;
10014         // generate color arrays for the surfaces in this list
10015         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10016         {
10017                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10018                 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)
10019                 {
10020                         f = RSurf_FogVertex(v);
10021                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10022                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10023                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10024                         c2[3] = c[3];
10025                 }
10026         }
10027         rsurface.lightmapcolor4f = rsurface.array_color4f;
10028         rsurface.lightmapcolor4f_bufferobject = 0;
10029         rsurface.lightmapcolor4f_bufferoffset = 0;
10030 }
10031
10032 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10033 {
10034         int texturesurfaceindex;
10035         int i;
10036         const float *c;
10037         float *c2;
10038         if (!rsurface.lightmapcolor4f)
10039                 return;
10040         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10041         {
10042                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10043                 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)
10044                 {
10045                         c2[0] = c[0] * r;
10046                         c2[1] = c[1] * g;
10047                         c2[2] = c[2] * b;
10048                         c2[3] = c[3] * a;
10049                 }
10050         }
10051         rsurface.lightmapcolor4f = rsurface.array_color4f;
10052         rsurface.lightmapcolor4f_bufferobject = 0;
10053         rsurface.lightmapcolor4f_bufferoffset = 0;
10054 }
10055
10056 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10057 {
10058         int texturesurfaceindex;
10059         int i;
10060         const float *c;
10061         float *c2;
10062         if (!rsurface.lightmapcolor4f)
10063                 return;
10064         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10065         {
10066                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10067                 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)
10068                 {
10069                         c2[0] = c[0] + r_refdef.scene.ambient;
10070                         c2[1] = c[1] + r_refdef.scene.ambient;
10071                         c2[2] = c[2] + r_refdef.scene.ambient;
10072                         c2[3] = c[3];
10073                 }
10074         }
10075         rsurface.lightmapcolor4f = rsurface.array_color4f;
10076         rsurface.lightmapcolor4f_bufferobject = 0;
10077         rsurface.lightmapcolor4f_bufferoffset = 0;
10078 }
10079
10080 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10081 {
10082         // TODO: optimize
10083         rsurface.lightmapcolor4f = NULL;
10084         rsurface.lightmapcolor4f_bufferobject = 0;
10085         rsurface.lightmapcolor4f_bufferoffset = 0;
10086         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10087         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10088         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10089         GL_Color(r, g, b, a);
10090         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10091 }
10092
10093 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10094 {
10095         // TODO: optimize applyfog && applycolor case
10096         // just apply fog if necessary, and tint the fog color array if necessary
10097         rsurface.lightmapcolor4f = NULL;
10098         rsurface.lightmapcolor4f_bufferobject = 0;
10099         rsurface.lightmapcolor4f_bufferoffset = 0;
10100         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10101         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10102         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10103         GL_Color(r, g, b, a);
10104         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10105 }
10106
10107 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10108 {
10109         int texturesurfaceindex;
10110         int i;
10111         float *c;
10112         // TODO: optimize
10113         if (texturesurfacelist[0]->lightmapinfo)
10114         {
10115                 // generate color arrays for the surfaces in this list
10116                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10117                 {
10118                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10119                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10120                         {
10121                                 if (surface->lightmapinfo->samples)
10122                                 {
10123                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10124                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10125                                         VectorScale(lm, scale, c);
10126                                         if (surface->lightmapinfo->styles[1] != 255)
10127                                         {
10128                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10129                                                 lm += size3;
10130                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10131                                                 VectorMA(c, scale, lm, c);
10132                                                 if (surface->lightmapinfo->styles[2] != 255)
10133                                                 {
10134                                                         lm += size3;
10135                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10136                                                         VectorMA(c, scale, lm, c);
10137                                                         if (surface->lightmapinfo->styles[3] != 255)
10138                                                         {
10139                                                                 lm += size3;
10140                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10141                                                                 VectorMA(c, scale, lm, c);
10142                                                         }
10143                                                 }
10144                                         }
10145                                 }
10146                                 else
10147                                         VectorClear(c);
10148                                 c[3] = 1;
10149                         }
10150                 }
10151                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10152                 rsurface.lightmapcolor4f_bufferobject = 0;
10153                 rsurface.lightmapcolor4f_bufferoffset = 0;
10154         }
10155         else
10156         {
10157                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10158                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10159                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10160         }
10161         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10162         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10163         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10164         GL_Color(r, g, b, a);
10165         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10166 }
10167
10168 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10169 {
10170         int texturesurfaceindex;
10171         int i;
10172         float f;
10173         float alpha;
10174         const float *v;
10175         const float *n;
10176         float *c;
10177         vec3_t ambientcolor;
10178         vec3_t diffusecolor;
10179         vec3_t lightdir;
10180         // TODO: optimize
10181         // model lighting
10182         VectorCopy(rsurface.modellight_lightdir, lightdir);
10183         f = 0.5f * r_refdef.lightmapintensity;
10184         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10185         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10186         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10187         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10188         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10189         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10190         alpha = *a;
10191         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10192         {
10193                 // generate color arrays for the surfaces in this list
10194                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10195                 {
10196                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10197                         int numverts = surface->num_vertices;
10198                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10199                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10200                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10201                         // q3-style directional shading
10202                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10203                         {
10204                                 if ((f = DotProduct(n, lightdir)) > 0)
10205                                         VectorMA(ambientcolor, f, diffusecolor, c);
10206                                 else
10207                                         VectorCopy(ambientcolor, c);
10208                                 c[3] = alpha;
10209                         }
10210                 }
10211                 *r = 1;
10212                 *g = 1;
10213                 *b = 1;
10214                 *a = 1;
10215                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10216                 rsurface.lightmapcolor4f_bufferobject = 0;
10217                 rsurface.lightmapcolor4f_bufferoffset = 0;
10218                 *applycolor = false;
10219         }
10220         else
10221         {
10222                 *r = ambientcolor[0];
10223                 *g = ambientcolor[1];
10224                 *b = ambientcolor[2];
10225                 rsurface.lightmapcolor4f = NULL;
10226                 rsurface.lightmapcolor4f_bufferobject = 0;
10227                 rsurface.lightmapcolor4f_bufferoffset = 0;
10228         }
10229 }
10230
10231 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10232 {
10233         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10234         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10235         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10236         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10237         GL_Color(r, g, b, a);
10238         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10239 }
10240
10241 void RSurf_SetupDepthAndCulling(void)
10242 {
10243         // submodels are biased to avoid z-fighting with world surfaces that they
10244         // may be exactly overlapping (avoids z-fighting artifacts on certain
10245         // doors and things in Quake maps)
10246         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10247         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10248         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10249         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10250 }
10251
10252 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10253 {
10254         // transparent sky would be ridiculous
10255         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10256                 return;
10257         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10258         skyrenderlater = true;
10259         RSurf_SetupDepthAndCulling();
10260         GL_DepthMask(true);
10261         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10262         // skymasking on them, and Quake3 never did sky masking (unlike
10263         // software Quake and software Quake2), so disable the sky masking
10264         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10265         // and skymasking also looks very bad when noclipping outside the
10266         // level, so don't use it then either.
10267         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10268         {
10269                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10270                 R_Mesh_ColorPointer(NULL, 0, 0);
10271                 R_Mesh_ResetTextureState();
10272                 if (skyrendermasked)
10273                 {
10274                         R_SetupShader_DepthOrShadow();
10275                         // depth-only (masking)
10276                         GL_ColorMask(0,0,0,0);
10277                         // just to make sure that braindead drivers don't draw
10278                         // anything despite that colormask...
10279                         GL_BlendFunc(GL_ZERO, GL_ONE);
10280                 }
10281                 else
10282                 {
10283                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10284                         // fog sky
10285                         GL_BlendFunc(GL_ONE, GL_ZERO);
10286                 }
10287                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10288                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10289                 if (skyrendermasked)
10290                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10291         }
10292         R_Mesh_ResetTextureState();
10293         GL_Color(1, 1, 1, 1);
10294 }
10295
10296 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10297 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10298 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10299 {
10300         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10301         if (prepass)
10302         {
10303                 // render screenspace normalmap to texture
10304                 GL_DepthMask(true);
10305                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10306                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10307                 GL_LockArrays(0, 0);
10308         }
10309         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10310         {
10311                 // render water or distortion background, then blend surface on top
10312                 GL_DepthMask(true);
10313                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10314                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10315                 GL_LockArrays(0, 0);
10316                 GL_DepthMask(false);
10317                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10318                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10319                 GL_LockArrays(0, 0);
10320         }
10321         else
10322         {
10323                 // render surface normally
10324                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10325                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10326                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10327                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10328                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10329                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10330                 else
10331                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10332                 GL_LockArrays(0, 0);
10333         }
10334 }
10335
10336 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10337 {
10338         // OpenGL 1.3 path - anything not completely ancient
10339         int texturesurfaceindex;
10340         qboolean applycolor;
10341         qboolean applyfog;
10342         int layerindex;
10343         const texturelayer_t *layer;
10344         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10345
10346         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10347         {
10348                 vec4_t layercolor;
10349                 int layertexrgbscale;
10350                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10351                 {
10352                         if (layerindex == 0)
10353                                 GL_AlphaTest(true);
10354                         else
10355                         {
10356                                 GL_AlphaTest(false);
10357                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10358                         }
10359                 }
10360                 GL_DepthMask(layer->depthmask && writedepth);
10361                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10362                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10363                 {
10364                         layertexrgbscale = 4;
10365                         VectorScale(layer->color, 0.25f, layercolor);
10366                 }
10367                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10368                 {
10369                         layertexrgbscale = 2;
10370                         VectorScale(layer->color, 0.5f, layercolor);
10371                 }
10372                 else
10373                 {
10374                         layertexrgbscale = 1;
10375                         VectorScale(layer->color, 1.0f, layercolor);
10376                 }
10377                 layercolor[3] = layer->color[3];
10378                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10379                 R_Mesh_ColorPointer(NULL, 0, 0);
10380                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10381                 switch (layer->type)
10382                 {
10383                 case TEXTURELAYERTYPE_LITTEXTURE:
10384                         // single-pass lightmapped texture with 2x rgbscale
10385                         //R_Mesh_TexBind(0, r_texture_white);
10386                         R_Mesh_TexMatrix(0, NULL);
10387                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10388                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10389                         R_Mesh_TexBind(1, layer->texture);
10390                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10391                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10392                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10393                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10394                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10395                         else if (rsurface.uselightmaptexture)
10396                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10397                         else
10398                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10399                         break;
10400                 case TEXTURELAYERTYPE_TEXTURE:
10401                         // singletexture unlit texture with transparency support
10402                         R_Mesh_TexBind(0, layer->texture);
10403                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10404                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10405                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10406                         R_Mesh_TexBind(1, 0);
10407                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10408                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10409                         break;
10410                 case TEXTURELAYERTYPE_FOG:
10411                         // singletexture fogging
10412                         if (layer->texture)
10413                         {
10414                                 R_Mesh_TexBind(0, layer->texture);
10415                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10416                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10417                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10418                         }
10419                         else
10420                         {
10421                                 R_Mesh_TexBind(0, 0);
10422                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10423                         }
10424                         R_Mesh_TexBind(1, 0);
10425                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10426                         // generate a color array for the fog pass
10427                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10428                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10429                         {
10430                                 int i;
10431                                 float f;
10432                                 const float *v;
10433                                 float *c;
10434                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10435                                 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)
10436                                 {
10437                                         f = 1 - RSurf_FogVertex(v);
10438                                         c[0] = layercolor[0];
10439                                         c[1] = layercolor[1];
10440                                         c[2] = layercolor[2];
10441                                         c[3] = f * layercolor[3];
10442                                 }
10443                         }
10444                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10445                         break;
10446                 default:
10447                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10448                 }
10449                 GL_LockArrays(0, 0);
10450         }
10451         CHECKGLERROR
10452         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10453         {
10454                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10455                 GL_AlphaTest(false);
10456         }
10457 }
10458
10459 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10460 {
10461         // OpenGL 1.1 - crusty old voodoo path
10462         int texturesurfaceindex;
10463         qboolean applyfog;
10464         int layerindex;
10465         const texturelayer_t *layer;
10466         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10467
10468         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10469         {
10470                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10471                 {
10472                         if (layerindex == 0)
10473                                 GL_AlphaTest(true);
10474                         else
10475                         {
10476                                 GL_AlphaTest(false);
10477                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10478                         }
10479                 }
10480                 GL_DepthMask(layer->depthmask && writedepth);
10481                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10482                 R_Mesh_ColorPointer(NULL, 0, 0);
10483                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10484                 switch (layer->type)
10485                 {
10486                 case TEXTURELAYERTYPE_LITTEXTURE:
10487                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10488                         {
10489                                 // two-pass lit texture with 2x rgbscale
10490                                 // first the lightmap pass
10491                                 //R_Mesh_TexBind(0, r_texture_white);
10492                                 R_Mesh_TexMatrix(0, NULL);
10493                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10494                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10495                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10496                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10497                                 else if (rsurface.uselightmaptexture)
10498                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10499                                 else
10500                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10501                                 GL_LockArrays(0, 0);
10502                                 // then apply the texture to it
10503                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10504                                 R_Mesh_TexBind(0, layer->texture);
10505                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10506                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10507                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10508                                 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);
10509                         }
10510                         else
10511                         {
10512                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10513                                 R_Mesh_TexBind(0, layer->texture);
10514                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10515                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10516                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10517                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10518                                         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);
10519                                 else
10520                                         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);
10521                         }
10522                         break;
10523                 case TEXTURELAYERTYPE_TEXTURE:
10524                         // singletexture unlit texture with transparency support
10525                         R_Mesh_TexBind(0, layer->texture);
10526                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10527                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10528                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10529                         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);
10530                         break;
10531                 case TEXTURELAYERTYPE_FOG:
10532                         // singletexture fogging
10533                         if (layer->texture)
10534                         {
10535                                 R_Mesh_TexBind(0, layer->texture);
10536                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10537                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10538                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10539                         }
10540                         else
10541                         {
10542                                 R_Mesh_TexBind(0, 0);
10543                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10544                         }
10545                         // generate a color array for the fog pass
10546                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10547                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10548                         {
10549                                 int i;
10550                                 float f;
10551                                 const float *v;
10552                                 float *c;
10553                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10554                                 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)
10555                                 {
10556                                         f = 1 - RSurf_FogVertex(v);
10557                                         c[0] = layer->color[0];
10558                                         c[1] = layer->color[1];
10559                                         c[2] = layer->color[2];
10560                                         c[3] = f * layer->color[3];
10561                                 }
10562                         }
10563                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10564                         break;
10565                 default:
10566                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10567                 }
10568                 GL_LockArrays(0, 0);
10569         }
10570         CHECKGLERROR
10571         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10572         {
10573                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10574                 GL_AlphaTest(false);
10575         }
10576 }
10577
10578 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10579 {
10580         float c[4];
10581
10582         GL_AlphaTest(false);
10583         R_Mesh_ColorPointer(NULL, 0, 0);
10584         R_Mesh_ResetTextureState();
10585         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10586
10587         if(rsurface.texture && rsurface.texture->currentskinframe)
10588         {
10589                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10590                 c[3] *= rsurface.texture->currentalpha;
10591         }
10592         else
10593         {
10594                 c[0] = 1;
10595                 c[1] = 0;
10596                 c[2] = 1;
10597                 c[3] = 1;
10598         }
10599
10600         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10601         {
10602                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10603                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10604                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10605         }
10606
10607         // brighten it up (as texture value 127 means "unlit")
10608         c[0] *= 2 * r_refdef.view.colorscale;
10609         c[1] *= 2 * r_refdef.view.colorscale;
10610         c[2] *= 2 * r_refdef.view.colorscale;
10611
10612         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10613                 c[3] *= r_wateralpha.value;
10614
10615         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10616         {
10617                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10618                 GL_DepthMask(false);
10619         }
10620         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10621         {
10622                 GL_BlendFunc(GL_ONE, GL_ONE);
10623                 GL_DepthMask(false);
10624         }
10625         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10626         {
10627                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10628                 GL_DepthMask(false);
10629         }
10630         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10631         {
10632                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10633                 GL_DepthMask(false);
10634         }
10635         else
10636         {
10637                 GL_BlendFunc(GL_ONE, GL_ZERO);
10638                 GL_DepthMask(writedepth);
10639         }
10640
10641         rsurface.lightmapcolor4f = NULL;
10642
10643         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10644         {
10645                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10646
10647                 rsurface.lightmapcolor4f = NULL;
10648                 rsurface.lightmapcolor4f_bufferobject = 0;
10649                 rsurface.lightmapcolor4f_bufferoffset = 0;
10650         }
10651         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10652         {
10653                 qboolean applycolor = true;
10654                 float one = 1.0;
10655
10656                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10657
10658                 r_refdef.lightmapintensity = 1;
10659                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10660                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10661         }
10662         else
10663         {
10664                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10665
10666                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10667                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10668                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10669         }
10670
10671         if(!rsurface.lightmapcolor4f)
10672                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10673
10674         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10675         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10676         if(r_refdef.fogenabled)
10677                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10678
10679         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10680         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10681 }
10682
10683 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10684 {
10685         CHECKGLERROR
10686         RSurf_SetupDepthAndCulling();
10687         if (r_showsurfaces.integer == 3 && !prepass)
10688         {
10689                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10690                 return;
10691         }
10692         switch (vid.renderpath)
10693         {
10694         case RENDERPATH_GL20:
10695         case RENDERPATH_CGGL:
10696                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10697                 break;
10698         case RENDERPATH_GL13:
10699                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10700                 break;
10701         case RENDERPATH_GL11:
10702                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10703                 break;
10704         }
10705         CHECKGLERROR
10706 }
10707
10708 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10709 {
10710         CHECKGLERROR
10711         RSurf_SetupDepthAndCulling();
10712         if (r_showsurfaces.integer == 3 && !prepass)
10713         {
10714                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10715                 return;
10716         }
10717         switch (vid.renderpath)
10718         {
10719         case RENDERPATH_GL20:
10720         case RENDERPATH_CGGL:
10721                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10722                 break;
10723         case RENDERPATH_GL13:
10724                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10725                 break;
10726         case RENDERPATH_GL11:
10727                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10728                 break;
10729         }
10730         CHECKGLERROR
10731 }
10732
10733 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10734 {
10735         int i, j;
10736         int texturenumsurfaces, endsurface;
10737         texture_t *texture;
10738         const msurface_t *surface;
10739         const msurface_t *texturesurfacelist[256];
10740
10741         // if the model is static it doesn't matter what value we give for
10742         // wantnormals and wanttangents, so this logic uses only rules applicable
10743         // to a model, knowing that they are meaningless otherwise
10744         if (ent == r_refdef.scene.worldentity)
10745                 RSurf_ActiveWorldEntity();
10746         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10747                 RSurf_ActiveModelEntity(ent, false, false, false);
10748         else
10749         {
10750                 switch (vid.renderpath)
10751                 {
10752                 case RENDERPATH_GL20:
10753                 case RENDERPATH_CGGL:
10754                         RSurf_ActiveModelEntity(ent, true, true, false);
10755                         break;
10756                 case RENDERPATH_GL13:
10757                 case RENDERPATH_GL11:
10758                         RSurf_ActiveModelEntity(ent, true, false, false);
10759                         break;
10760                 }
10761         }
10762
10763         if (r_transparentdepthmasking.integer)
10764         {
10765                 qboolean setup = false;
10766                 for (i = 0;i < numsurfaces;i = j)
10767                 {
10768                         j = i + 1;
10769                         surface = rsurface.modelsurfaces + surfacelist[i];
10770                         texture = surface->texture;
10771                         rsurface.texture = R_GetCurrentTexture(texture);
10772                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10773                         // scan ahead until we find a different texture
10774                         endsurface = min(i + 1024, numsurfaces);
10775                         texturenumsurfaces = 0;
10776                         texturesurfacelist[texturenumsurfaces++] = surface;
10777                         for (;j < endsurface;j++)
10778                         {
10779                                 surface = rsurface.modelsurfaces + surfacelist[j];
10780                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10781                                         break;
10782                                 texturesurfacelist[texturenumsurfaces++] = surface;
10783                         }
10784                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10785                                 continue;
10786                         // render the range of surfaces as depth
10787                         if (!setup)
10788                         {
10789                                 setup = true;
10790                                 GL_ColorMask(0,0,0,0);
10791                                 GL_Color(1,1,1,1);
10792                                 GL_DepthTest(true);
10793                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10794                                 GL_DepthMask(true);
10795                                 GL_AlphaTest(false);
10796                                 R_Mesh_ColorPointer(NULL, 0, 0);
10797                                 R_Mesh_ResetTextureState();
10798                                 R_SetupShader_DepthOrShadow();
10799                         }
10800                         RSurf_SetupDepthAndCulling();
10801                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10802                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10803                 }
10804                 if (setup)
10805                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10806         }
10807
10808         for (i = 0;i < numsurfaces;i = j)
10809         {
10810                 j = i + 1;
10811                 surface = rsurface.modelsurfaces + surfacelist[i];
10812                 texture = surface->texture;
10813                 rsurface.texture = R_GetCurrentTexture(texture);
10814                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10815                 // scan ahead until we find a different texture
10816                 endsurface = min(i + 1024, numsurfaces);
10817                 texturenumsurfaces = 0;
10818                 texturesurfacelist[texturenumsurfaces++] = surface;
10819                 for (;j < endsurface;j++)
10820                 {
10821                         surface = rsurface.modelsurfaces + surfacelist[j];
10822                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10823                                 break;
10824                         texturesurfacelist[texturenumsurfaces++] = surface;
10825                 }
10826                 // render the range of surfaces
10827                 if (ent == r_refdef.scene.worldentity)
10828                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10829                 else
10830                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10831         }
10832         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10833         GL_AlphaTest(false);
10834 }
10835
10836 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10837 {
10838         // transparent surfaces get pushed off into the transparent queue
10839         int surfacelistindex;
10840         const msurface_t *surface;
10841         vec3_t tempcenter, center;
10842         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10843         {
10844                 surface = texturesurfacelist[surfacelistindex];
10845                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10846                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10847                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10848                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10849                 if (queueentity->transparent_offset) // transparent offset
10850                 {
10851                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10852                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10853                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10854                 }
10855                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10856         }
10857 }
10858
10859 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10860 {
10861         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10862         CHECKGLERROR
10863         if (depthonly)
10864         {
10865                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10866                         return;
10867                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10868                         return;
10869                 RSurf_SetupDepthAndCulling();
10870                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10871                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10872         }
10873         else if (prepass)
10874         {
10875                 if (!rsurface.texture->currentnumlayers)
10876                         return;
10877                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10878                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10879                 else
10880                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10881         }
10882         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10883         {
10884                 RSurf_SetupDepthAndCulling();
10885                 GL_AlphaTest(false);
10886                 R_Mesh_ColorPointer(NULL, 0, 0);
10887                 R_Mesh_ResetTextureState();
10888                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10889                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10890                 GL_DepthMask(true);
10891                 GL_BlendFunc(GL_ONE, GL_ZERO);
10892                 GL_Color(0, 0, 0, 1);
10893                 GL_DepthTest(writedepth);
10894                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10895         }
10896         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10897         {
10898                 RSurf_SetupDepthAndCulling();
10899                 GL_AlphaTest(false);
10900                 R_Mesh_ColorPointer(NULL, 0, 0);
10901                 R_Mesh_ResetTextureState();
10902                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10903                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10904                 GL_DepthMask(true);
10905                 GL_BlendFunc(GL_ONE, GL_ZERO);
10906                 GL_DepthTest(true);
10907                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10908         }
10909         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10910                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10911         else if (!rsurface.texture->currentnumlayers)
10912                 return;
10913         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10914         {
10915                 // in the deferred case, transparent surfaces were queued during prepass
10916                 if (!r_shadow_usingdeferredprepass)
10917                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10918         }
10919         else
10920         {
10921                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10922                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10923         }
10924         CHECKGLERROR
10925 }
10926
10927 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10928 {
10929         int i, j;
10930         texture_t *texture;
10931         // break the surface list down into batches by texture and use of lightmapping
10932         for (i = 0;i < numsurfaces;i = j)
10933         {
10934                 j = i + 1;
10935                 // texture is the base texture pointer, rsurface.texture is the
10936                 // current frame/skin the texture is directing us to use (for example
10937                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10938                 // use skin 1 instead)
10939                 texture = surfacelist[i]->texture;
10940                 rsurface.texture = R_GetCurrentTexture(texture);
10941                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10942                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10943                 {
10944                         // if this texture is not the kind we want, skip ahead to the next one
10945                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10946                                 ;
10947                         continue;
10948                 }
10949                 // simply scan ahead until we find a different texture or lightmap state
10950                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10951                         ;
10952                 // render the range of surfaces
10953                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10954         }
10955 }
10956
10957 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10958 {
10959         CHECKGLERROR
10960         if (depthonly)
10961         {
10962                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10963                         return;
10964                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10965                         return;
10966                 RSurf_SetupDepthAndCulling();
10967                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10968                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10969         }
10970         else if (prepass)
10971         {
10972                 if (!rsurface.texture->currentnumlayers)
10973                         return;
10974                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10975                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10976                 else
10977                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10978         }
10979         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10980         {
10981                 RSurf_SetupDepthAndCulling();
10982                 GL_AlphaTest(false);
10983                 R_Mesh_ColorPointer(NULL, 0, 0);
10984                 R_Mesh_ResetTextureState();
10985                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10986                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10987                 GL_DepthMask(true);
10988                 GL_BlendFunc(GL_ONE, GL_ZERO);
10989                 GL_Color(0, 0, 0, 1);
10990                 GL_DepthTest(writedepth);
10991                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10992         }
10993         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10994         {
10995                 RSurf_SetupDepthAndCulling();
10996                 GL_AlphaTest(false);
10997                 R_Mesh_ColorPointer(NULL, 0, 0);
10998                 R_Mesh_ResetTextureState();
10999                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11000                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11001                 GL_DepthMask(true);
11002                 GL_BlendFunc(GL_ONE, GL_ZERO);
11003                 GL_DepthTest(true);
11004                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11005         }
11006         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11007                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11008         else if (!rsurface.texture->currentnumlayers)
11009                 return;
11010         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11011         {
11012                 // in the deferred case, transparent surfaces were queued during prepass
11013                 if (!r_shadow_usingdeferredprepass)
11014                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11015         }
11016         else
11017         {
11018                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11019                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11020         }
11021         CHECKGLERROR
11022 }
11023
11024 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11025 {
11026         int i, j;
11027         texture_t *texture;
11028         // break the surface list down into batches by texture and use of lightmapping
11029         for (i = 0;i < numsurfaces;i = j)
11030         {
11031                 j = i + 1;
11032                 // texture is the base texture pointer, rsurface.texture is the
11033                 // current frame/skin the texture is directing us to use (for example
11034                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11035                 // use skin 1 instead)
11036                 texture = surfacelist[i]->texture;
11037                 rsurface.texture = R_GetCurrentTexture(texture);
11038                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11039                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11040                 {
11041                         // if this texture is not the kind we want, skip ahead to the next one
11042                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11043                                 ;
11044                         continue;
11045                 }
11046                 // simply scan ahead until we find a different texture or lightmap state
11047                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11048                         ;
11049                 // render the range of surfaces
11050                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11051         }
11052 }
11053
11054 float locboxvertex3f[6*4*3] =
11055 {
11056         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11057         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11058         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11059         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11060         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11061         1,0,0, 0,0,0, 0,1,0, 1,1,0
11062 };
11063
11064 unsigned short locboxelements[6*2*3] =
11065 {
11066          0, 1, 2, 0, 2, 3,
11067          4, 5, 6, 4, 6, 7,
11068          8, 9,10, 8,10,11,
11069         12,13,14, 12,14,15,
11070         16,17,18, 16,18,19,
11071         20,21,22, 20,22,23
11072 };
11073
11074 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11075 {
11076         int i, j;
11077         cl_locnode_t *loc = (cl_locnode_t *)ent;
11078         vec3_t mins, size;
11079         float vertex3f[6*4*3];
11080         CHECKGLERROR
11081         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11082         GL_DepthMask(false);
11083         GL_DepthRange(0, 1);
11084         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11085         GL_DepthTest(true);
11086         GL_CullFace(GL_NONE);
11087         R_EntityMatrix(&identitymatrix);
11088
11089         R_Mesh_VertexPointer(vertex3f, 0, 0);
11090         R_Mesh_ColorPointer(NULL, 0, 0);
11091         R_Mesh_ResetTextureState();
11092         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11093
11094         i = surfacelist[0];
11095         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11096                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11097                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11098                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11099
11100         if (VectorCompare(loc->mins, loc->maxs))
11101         {
11102                 VectorSet(size, 2, 2, 2);
11103                 VectorMA(loc->mins, -0.5f, size, mins);
11104         }
11105         else
11106         {
11107                 VectorCopy(loc->mins, mins);
11108                 VectorSubtract(loc->maxs, loc->mins, size);
11109         }
11110
11111         for (i = 0;i < 6*4*3;)
11112                 for (j = 0;j < 3;j++, i++)
11113                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11114
11115         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11116 }
11117
11118 void R_DrawLocs(void)
11119 {
11120         int index;
11121         cl_locnode_t *loc, *nearestloc;
11122         vec3_t center;
11123         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11124         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11125         {
11126                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11127                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11128         }
11129 }
11130
11131 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11132 {
11133         if (decalsystem->decals)
11134                 Mem_Free(decalsystem->decals);
11135         memset(decalsystem, 0, sizeof(*decalsystem));
11136 }
11137
11138 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)
11139 {
11140         tridecal_t *decal;
11141         tridecal_t *decals;
11142         int i;
11143         int maxdecals;
11144
11145         // expand or initialize the system
11146         if (decalsystem->maxdecals <= decalsystem->numdecals)
11147         {
11148                 decalsystem_t old = *decalsystem;
11149                 qboolean useshortelements;
11150                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11151                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11152                 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)));
11153                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11154                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11155                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11156                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11157                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11158                 if (decalsystem->numdecals)
11159                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11160                 if (old.decals)
11161                         Mem_Free(old.decals);
11162                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11163                         decalsystem->element3i[i] = i;
11164                 if (useshortelements)
11165                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11166                                 decalsystem->element3s[i] = i;
11167         }
11168
11169         // grab a decal and search for another free slot for the next one
11170         maxdecals = decalsystem->maxdecals;
11171         decals = decalsystem->decals;
11172         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11173         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11174                 ;
11175         decalsystem->freedecal = i;
11176         if (decalsystem->numdecals <= i)
11177                 decalsystem->numdecals = i + 1;
11178
11179         // initialize the decal
11180         decal->lived = 0;
11181         decal->triangleindex = triangleindex;
11182         decal->surfaceindex = surfaceindex;
11183         decal->decalsequence = decalsequence;
11184         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11185         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11186         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11187         decal->color4ub[0][3] = 255;
11188         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11189         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11190         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11191         decal->color4ub[1][3] = 255;
11192         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11193         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11194         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11195         decal->color4ub[2][3] = 255;
11196         decal->vertex3f[0][0] = v0[0];
11197         decal->vertex3f[0][1] = v0[1];
11198         decal->vertex3f[0][2] = v0[2];
11199         decal->vertex3f[1][0] = v1[0];
11200         decal->vertex3f[1][1] = v1[1];
11201         decal->vertex3f[1][2] = v1[2];
11202         decal->vertex3f[2][0] = v2[0];
11203         decal->vertex3f[2][1] = v2[1];
11204         decal->vertex3f[2][2] = v2[2];
11205         decal->texcoord2f[0][0] = t0[0];
11206         decal->texcoord2f[0][1] = t0[1];
11207         decal->texcoord2f[1][0] = t1[0];
11208         decal->texcoord2f[1][1] = t1[1];
11209         decal->texcoord2f[2][0] = t2[0];
11210         decal->texcoord2f[2][1] = t2[1];
11211 }
11212
11213 extern cvar_t cl_decals_bias;
11214 extern cvar_t cl_decals_models;
11215 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11216 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)
11217 {
11218         matrix4x4_t projection;
11219         decalsystem_t *decalsystem;
11220         qboolean dynamic;
11221         dp_model_t *model;
11222         const float *vertex3f;
11223         const msurface_t *surface;
11224         const msurface_t *surfaces;
11225         const int *surfacelist;
11226         const texture_t *texture;
11227         int numvertices;
11228         int numtriangles;
11229         int numsurfacelist;
11230         int surfacelistindex;
11231         int surfaceindex;
11232         int triangleindex;
11233         int decalsurfaceindex;
11234         int cornerindex;
11235         int index;
11236         int numpoints;
11237         const int *e;
11238         float localorigin[3];
11239         float localnormal[3];
11240         float localmins[3];
11241         float localmaxs[3];
11242         float localsize;
11243         float ilocalsize;
11244         float v[9][3];
11245         float tc[9][2];
11246         float c[9][4];
11247         //float normal[3];
11248         float planes[6][4];
11249         float f;
11250         float points[2][9][3];
11251         float angles[3];
11252         float temp[3];
11253
11254         decalsystem = &ent->decalsystem;
11255         model = ent->model;
11256         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11257         {
11258                 R_DecalSystem_Reset(&ent->decalsystem);
11259                 return;
11260         }
11261
11262         if (!model->brush.data_nodes && !cl_decals_models.integer)
11263         {
11264                 if (decalsystem->model)
11265                         R_DecalSystem_Reset(decalsystem);
11266                 return;
11267         }
11268
11269         if (decalsystem->model != model)
11270                 R_DecalSystem_Reset(decalsystem);
11271         decalsystem->model = model;
11272
11273         RSurf_ActiveModelEntity(ent, false, false, false);
11274
11275         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11276         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11277         VectorNormalize(localnormal);
11278         localsize = worldsize*rsurface.inversematrixscale;
11279         ilocalsize = 1.0f / localsize;
11280         localmins[0] = localorigin[0] - localsize;
11281         localmins[1] = localorigin[1] - localsize;
11282         localmins[2] = localorigin[2] - localsize;
11283         localmaxs[0] = localorigin[0] + localsize;
11284         localmaxs[1] = localorigin[1] + localsize;
11285         localmaxs[2] = localorigin[2] + localsize;
11286
11287         //VectorCopy(localnormal, planes[4]);
11288         //VectorVectors(planes[4], planes[2], planes[0]);
11289         AnglesFromVectors(angles, localnormal, NULL, false);
11290         AngleVectors(angles, planes[0], planes[2], planes[4]);
11291         VectorNegate(planes[0], planes[1]);
11292         VectorNegate(planes[2], planes[3]);
11293         VectorNegate(planes[4], planes[5]);
11294         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11295         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11296         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11297         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11298         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11299         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11300
11301 #if 1
11302 // works
11303 {
11304         matrix4x4_t forwardprojection;
11305         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11306         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11307 }
11308 #else
11309 // broken
11310 {
11311         float projectionvector[4][3];
11312         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11313         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11314         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11315         projectionvector[0][0] = planes[0][0] * ilocalsize;
11316         projectionvector[0][1] = planes[1][0] * ilocalsize;
11317         projectionvector[0][2] = planes[2][0] * ilocalsize;
11318         projectionvector[1][0] = planes[0][1] * ilocalsize;
11319         projectionvector[1][1] = planes[1][1] * ilocalsize;
11320         projectionvector[1][2] = planes[2][1] * ilocalsize;
11321         projectionvector[2][0] = planes[0][2] * ilocalsize;
11322         projectionvector[2][1] = planes[1][2] * ilocalsize;
11323         projectionvector[2][2] = planes[2][2] * ilocalsize;
11324         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11325         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11326         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11327         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11328 }
11329 #endif
11330
11331         dynamic = model->surfmesh.isanimated;
11332         vertex3f = rsurface.modelvertex3f;
11333         numsurfacelist = model->nummodelsurfaces;
11334         surfacelist = model->sortedmodelsurfaces;
11335         surfaces = model->data_surfaces;
11336         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11337         {
11338                 surfaceindex = surfacelist[surfacelistindex];
11339                 surface = surfaces + surfaceindex;
11340                 // skip transparent surfaces
11341                 texture = surface->texture;
11342                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11343                         continue;
11344                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11345                         continue;
11346                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11347                         continue;
11348                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11349                 numvertices = surface->num_vertices;
11350                 numtriangles = surface->num_triangles;
11351                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11352                 {
11353                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11354                         {
11355                                 index = 3*e[cornerindex];
11356                                 VectorCopy(vertex3f + index, v[cornerindex]);
11357                         }
11358                         // cull backfaces
11359                         //TriangleNormal(v[0], v[1], v[2], normal);
11360                         //if (DotProduct(normal, localnormal) < 0.0f)
11361                         //      continue;
11362                         // clip by each of the box planes formed from the projection matrix
11363                         // if anything survives, we emit the decal
11364                         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]);
11365                         if (numpoints < 3)
11366                                 continue;
11367                         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]);
11368                         if (numpoints < 3)
11369                                 continue;
11370                         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]);
11371                         if (numpoints < 3)
11372                                 continue;
11373                         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]);
11374                         if (numpoints < 3)
11375                                 continue;
11376                         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]);
11377                         if (numpoints < 3)
11378                                 continue;
11379                         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]);
11380                         if (numpoints < 3)
11381                                 continue;
11382                         // some part of the triangle survived, so we have to accept it...
11383                         if (dynamic)
11384                         {
11385                                 // dynamic always uses the original triangle
11386                                 numpoints = 3;
11387                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11388                                 {
11389                                         index = 3*e[cornerindex];
11390                                         VectorCopy(vertex3f + index, v[cornerindex]);
11391                                 }
11392                         }
11393                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11394                         {
11395                                 // convert vertex positions to texcoords
11396                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11397                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11398                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11399                                 // calculate distance fade from the projection origin
11400                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11401                                 f = bound(0.0f, f, 1.0f);
11402                                 c[cornerindex][0] = r * f;
11403                                 c[cornerindex][1] = g * f;
11404                                 c[cornerindex][2] = b * f;
11405                                 c[cornerindex][3] = 1.0f;
11406                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11407                         }
11408                         if (dynamic)
11409                                 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);
11410                         else
11411                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11412                                         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);
11413                 }
11414         }
11415 }
11416
11417 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11418 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)
11419 {
11420         int renderentityindex;
11421         float worldmins[3];
11422         float worldmaxs[3];
11423         entity_render_t *ent;
11424
11425         if (!cl_decals_newsystem.integer)
11426                 return;
11427
11428         worldmins[0] = worldorigin[0] - worldsize;
11429         worldmins[1] = worldorigin[1] - worldsize;
11430         worldmins[2] = worldorigin[2] - worldsize;
11431         worldmaxs[0] = worldorigin[0] + worldsize;
11432         worldmaxs[1] = worldorigin[1] + worldsize;
11433         worldmaxs[2] = worldorigin[2] + worldsize;
11434
11435         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11436
11437         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11438         {
11439                 ent = r_refdef.scene.entities[renderentityindex];
11440                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11441                         continue;
11442
11443                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11444         }
11445 }
11446
11447 typedef struct r_decalsystem_splatqueue_s
11448 {
11449         vec3_t worldorigin;
11450         vec3_t worldnormal;
11451         float color[4];
11452         float tcrange[4];
11453         float worldsize;
11454         int decalsequence;
11455 }
11456 r_decalsystem_splatqueue_t;
11457
11458 int r_decalsystem_numqueued = 0;
11459 #define MAX_DECALSYSTEM_QUEUE 1024
11460 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11461
11462 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)
11463 {
11464         r_decalsystem_splatqueue_t *queue;
11465
11466         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11467                 return;
11468
11469         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11470         VectorCopy(worldorigin, queue->worldorigin);
11471         VectorCopy(worldnormal, queue->worldnormal);
11472         Vector4Set(queue->color, r, g, b, a);
11473         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11474         queue->worldsize = worldsize;
11475         queue->decalsequence = cl.decalsequence++;
11476 }
11477
11478 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11479 {
11480         int i;
11481         r_decalsystem_splatqueue_t *queue;
11482
11483         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11484                 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);
11485         r_decalsystem_numqueued = 0;
11486 }
11487
11488 extern cvar_t cl_decals_max;
11489 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11490 {
11491         int i;
11492         decalsystem_t *decalsystem = &ent->decalsystem;
11493         int numdecals;
11494         int killsequence;
11495         tridecal_t *decal;
11496         float frametime;
11497         float lifetime;
11498
11499         if (!decalsystem->numdecals)
11500                 return;
11501
11502         if (r_showsurfaces.integer)
11503                 return;
11504
11505         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11506         {
11507                 R_DecalSystem_Reset(decalsystem);
11508                 return;
11509         }
11510
11511         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11512         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11513
11514         if (decalsystem->lastupdatetime)
11515                 frametime = (cl.time - decalsystem->lastupdatetime);
11516         else
11517                 frametime = 0;
11518         decalsystem->lastupdatetime = cl.time;
11519         decal = decalsystem->decals;
11520         numdecals = decalsystem->numdecals;
11521
11522         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11523         {
11524                 if (decal->color4ub[0][3])
11525                 {
11526                         decal->lived += frametime;
11527                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11528                         {
11529                                 memset(decal, 0, sizeof(*decal));
11530                                 if (decalsystem->freedecal > i)
11531                                         decalsystem->freedecal = i;
11532                         }
11533                 }
11534         }
11535         decal = decalsystem->decals;
11536         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11537                 numdecals--;
11538
11539         // collapse the array by shuffling the tail decals into the gaps
11540         for (;;)
11541         {
11542                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11543                         decalsystem->freedecal++;
11544                 if (decalsystem->freedecal == numdecals)
11545                         break;
11546                 decal[decalsystem->freedecal] = decal[--numdecals];
11547         }
11548
11549         decalsystem->numdecals = numdecals;
11550
11551         if (numdecals <= 0)
11552         {
11553                 // if there are no decals left, reset decalsystem
11554                 R_DecalSystem_Reset(decalsystem);
11555         }
11556 }
11557
11558 extern skinframe_t *decalskinframe;
11559 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11560 {
11561         int i;
11562         decalsystem_t *decalsystem = &ent->decalsystem;
11563         int numdecals;
11564         tridecal_t *decal;
11565         float fadedelay;
11566         float faderate;
11567         float alpha;
11568         float *v3f;
11569         float *c4f;
11570         float *t2f;
11571         const int *e;
11572         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11573         int numtris = 0;
11574
11575         numdecals = decalsystem->numdecals;
11576         if (!numdecals)
11577                 return;
11578
11579         if (r_showsurfaces.integer)
11580                 return;
11581
11582         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11583         {
11584                 R_DecalSystem_Reset(decalsystem);
11585                 return;
11586         }
11587
11588         // if the model is static it doesn't matter what value we give for
11589         // wantnormals and wanttangents, so this logic uses only rules applicable
11590         // to a model, knowing that they are meaningless otherwise
11591         if (ent == r_refdef.scene.worldentity)
11592                 RSurf_ActiveWorldEntity();
11593         else
11594                 RSurf_ActiveModelEntity(ent, false, false, false);
11595
11596         decalsystem->lastupdatetime = cl.time;
11597         decal = decalsystem->decals;
11598
11599         fadedelay = cl_decals_time.value;
11600         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11601
11602         // update vertex positions for animated models
11603         v3f = decalsystem->vertex3f;
11604         c4f = decalsystem->color4f;
11605         t2f = decalsystem->texcoord2f;
11606         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11607         {
11608                 if (!decal->color4ub[0][3])
11609                         continue;
11610
11611                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11612                         continue;
11613
11614                 // update color values for fading decals
11615                 if (decal->lived >= cl_decals_time.value)
11616                 {
11617                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11618                         alpha *= (1.0f/255.0f);
11619                 }
11620                 else
11621                         alpha = 1.0f/255.0f;
11622
11623                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11624                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11625                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11626                 c4f[ 3] = 1;
11627                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11628                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11629                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11630                 c4f[ 7] = 1;
11631                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11632                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11633                 c4f[10] = decal->color4ub[2][2] * alpha;
11634                 c4f[11] = 1;
11635
11636                 t2f[0] = decal->texcoord2f[0][0];
11637                 t2f[1] = decal->texcoord2f[0][1];
11638                 t2f[2] = decal->texcoord2f[1][0];
11639                 t2f[3] = decal->texcoord2f[1][1];
11640                 t2f[4] = decal->texcoord2f[2][0];
11641                 t2f[5] = decal->texcoord2f[2][1];
11642
11643                 // update vertex positions for animated models
11644                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11645                 {
11646                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11647                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11648                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11649                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11650                 }
11651                 else
11652                 {
11653                         VectorCopy(decal->vertex3f[0], v3f);
11654                         VectorCopy(decal->vertex3f[1], v3f + 3);
11655                         VectorCopy(decal->vertex3f[2], v3f + 6);
11656                 }
11657
11658                 v3f += 9;
11659                 c4f += 12;
11660                 t2f += 6;
11661                 numtris++;
11662         }
11663
11664         if (numtris > 0)
11665         {
11666                 r_refdef.stats.drawndecals += numtris;
11667
11668                 if (r_refdef.fogenabled)
11669                 {
11670                         switch(vid.renderpath)
11671                         {
11672                         case RENDERPATH_GL20:
11673                         case RENDERPATH_CGGL:
11674                         case RENDERPATH_GL13:
11675                         case RENDERPATH_GL11:
11676                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11677                                 {
11678                                         alpha = RSurf_FogVertex(v3f);
11679                                         c4f[0] *= alpha;
11680                                         c4f[1] *= alpha;
11681                                         c4f[2] *= alpha;
11682                                 }
11683                                 break;
11684                         }
11685                 }
11686
11687                 // now render the decals all at once
11688                 // (this assumes they all use one particle font texture!)
11689                 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);
11690                 R_Mesh_ResetTextureState();
11691                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11692                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11693                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11694                 GL_DepthMask(false);
11695                 GL_DepthRange(0, 1);
11696                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11697                 GL_DepthTest(true);
11698                 GL_CullFace(GL_NONE);
11699                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11700                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11701                 GL_LockArrays(0, numtris * 3);
11702                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11703                 GL_LockArrays(0, 0);
11704         }
11705 }
11706
11707 static void R_DrawModelDecals(void)
11708 {
11709         int i, numdecals;
11710
11711         // fade faster when there are too many decals
11712         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11713         for (i = 0;i < r_refdef.scene.numentities;i++)
11714                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11715
11716         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11717         for (i = 0;i < r_refdef.scene.numentities;i++)
11718                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11719                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11720
11721         R_DecalSystem_ApplySplatEntitiesQueue();
11722
11723         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11724         for (i = 0;i < r_refdef.scene.numentities;i++)
11725                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11726
11727         r_refdef.stats.totaldecals += numdecals;
11728
11729         if (r_showsurfaces.integer)
11730                 return;
11731
11732         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11733
11734         for (i = 0;i < r_refdef.scene.numentities;i++)
11735         {
11736                 if (!r_refdef.viewcache.entityvisible[i])
11737                         continue;
11738                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11739                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11740         }
11741 }
11742
11743 void R_DrawDebugModel(void)
11744 {
11745         entity_render_t *ent = rsurface.entity;
11746         int i, j, k, l, flagsmask;
11747         const int *elements;
11748         q3mbrush_t *brush;
11749         const msurface_t *surface;
11750         dp_model_t *model = ent->model;
11751         vec3_t v;
11752
11753         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11754
11755         R_Mesh_ColorPointer(NULL, 0, 0);
11756         R_Mesh_ResetTextureState();
11757         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11758         GL_DepthRange(0, 1);
11759         GL_DepthTest(!r_showdisabledepthtest.integer);
11760         GL_DepthMask(false);
11761         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11762
11763         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11764         {
11765                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11766                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11767                 {
11768                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11769                         {
11770                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11771                                 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);
11772                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11773                         }
11774                 }
11775                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11776                 {
11777                         if (surface->num_collisiontriangles)
11778                         {
11779                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11780                                 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);
11781                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11782                         }
11783                 }
11784         }
11785
11786         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11787
11788         if (r_showtris.integer || r_shownormals.integer)
11789         {
11790                 if (r_showdisabledepthtest.integer)
11791                 {
11792                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11793                         GL_DepthMask(false);
11794                 }
11795                 else
11796                 {
11797                         GL_BlendFunc(GL_ONE, GL_ZERO);
11798                         GL_DepthMask(true);
11799                 }
11800                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11801                 {
11802                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11803                                 continue;
11804                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11805                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11806                         {
11807                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11808                                 if (r_showtris.value > 0)
11809                                 {
11810                                         if (!rsurface.texture->currentlayers->depthmask)
11811                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11812                                         else if (ent == r_refdef.scene.worldentity)
11813                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11814                                         else
11815                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11816                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11817                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11818                                         R_Mesh_ColorPointer(NULL, 0, 0);
11819                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11820                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11821                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11822                                         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);
11823                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11824                                         CHECKGLERROR
11825                                 }
11826                                 if (r_shownormals.value < 0)
11827                                 {
11828                                         qglBegin(GL_LINES);
11829                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11830                                         {
11831                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11832                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11833                                                 qglVertex3f(v[0], v[1], v[2]);
11834                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11835                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11836                                                 qglVertex3f(v[0], v[1], v[2]);
11837                                         }
11838                                         qglEnd();
11839                                         CHECKGLERROR
11840                                 }
11841                                 if (r_shownormals.value > 0)
11842                                 {
11843                                         qglBegin(GL_LINES);
11844                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11845                                         {
11846                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11847                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11848                                                 qglVertex3f(v[0], v[1], v[2]);
11849                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11850                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11851                                                 qglVertex3f(v[0], v[1], v[2]);
11852                                         }
11853                                         qglEnd();
11854                                         CHECKGLERROR
11855                                         qglBegin(GL_LINES);
11856                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11857                                         {
11858                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11859                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11860                                                 qglVertex3f(v[0], v[1], v[2]);
11861                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11862                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11863                                                 qglVertex3f(v[0], v[1], v[2]);
11864                                         }
11865                                         qglEnd();
11866                                         CHECKGLERROR
11867                                         qglBegin(GL_LINES);
11868                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11869                                         {
11870                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11871                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11872                                                 qglVertex3f(v[0], v[1], v[2]);
11873                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11874                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11875                                                 qglVertex3f(v[0], v[1], v[2]);
11876                                         }
11877                                         qglEnd();
11878                                         CHECKGLERROR
11879                                 }
11880                         }
11881                 }
11882                 rsurface.texture = NULL;
11883         }
11884 }
11885
11886 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11887 int r_maxsurfacelist = 0;
11888 const msurface_t **r_surfacelist = NULL;
11889 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11890 {
11891         int i, j, endj, f, flagsmask;
11892         texture_t *t;
11893         dp_model_t *model = r_refdef.scene.worldmodel;
11894         msurface_t *surfaces;
11895         unsigned char *update;
11896         int numsurfacelist = 0;
11897         if (model == NULL)
11898                 return;
11899
11900         if (r_maxsurfacelist < model->num_surfaces)
11901         {
11902                 r_maxsurfacelist = model->num_surfaces;
11903                 if (r_surfacelist)
11904                         Mem_Free((msurface_t**)r_surfacelist);
11905                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11906         }
11907
11908         RSurf_ActiveWorldEntity();
11909
11910         surfaces = model->data_surfaces;
11911         update = model->brushq1.lightmapupdateflags;
11912
11913         // update light styles on this submodel
11914         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11915         {
11916                 model_brush_lightstyleinfo_t *style;
11917                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11918                 {
11919                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11920                         {
11921                                 int *list = style->surfacelist;
11922                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11923                                 for (j = 0;j < style->numsurfaces;j++)
11924                                         update[list[j]] = true;
11925                         }
11926                 }
11927         }
11928
11929         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11930
11931         if (debug)
11932         {
11933                 R_DrawDebugModel();
11934                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11935                 return;
11936         }
11937
11938         f = 0;
11939         t = NULL;
11940         rsurface.uselightmaptexture = false;
11941         rsurface.texture = NULL;
11942         rsurface.rtlight = NULL;
11943         numsurfacelist = 0;
11944         // add visible surfaces to draw list
11945         for (i = 0;i < model->nummodelsurfaces;i++)
11946         {
11947                 j = model->sortedmodelsurfaces[i];
11948                 if (r_refdef.viewcache.world_surfacevisible[j])
11949                         r_surfacelist[numsurfacelist++] = surfaces + j;
11950         }
11951         // update lightmaps if needed
11952         if (model->brushq1.firstrender)
11953         {
11954                 model->brushq1.firstrender = false;
11955                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11956                         if (update[j])
11957                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11958         }
11959         else if (update)
11960         {
11961                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11962                         if (r_refdef.viewcache.world_surfacevisible[j])
11963                                 if (update[j])
11964                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11965         }
11966         // don't do anything if there were no surfaces
11967         if (!numsurfacelist)
11968         {
11969                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11970                 return;
11971         }
11972         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11973         GL_AlphaTest(false);
11974
11975         // add to stats if desired
11976         if (r_speeds.integer && !skysurfaces && !depthonly)
11977         {
11978                 r_refdef.stats.world_surfaces += numsurfacelist;
11979                 for (j = 0;j < numsurfacelist;j++)
11980                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11981         }
11982
11983         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11984 }
11985
11986 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11987 {
11988         int i, j, endj, f, flagsmask;
11989         texture_t *t;
11990         dp_model_t *model = ent->model;
11991         msurface_t *surfaces;
11992         unsigned char *update;
11993         int numsurfacelist = 0;
11994         if (model == NULL)
11995                 return;
11996
11997         if (r_maxsurfacelist < model->num_surfaces)
11998         {
11999                 r_maxsurfacelist = model->num_surfaces;
12000                 if (r_surfacelist)
12001                         Mem_Free((msurface_t **)r_surfacelist);
12002                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12003         }
12004
12005         // if the model is static it doesn't matter what value we give for
12006         // wantnormals and wanttangents, so this logic uses only rules applicable
12007         // to a model, knowing that they are meaningless otherwise
12008         if (ent == r_refdef.scene.worldentity)
12009                 RSurf_ActiveWorldEntity();
12010         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12011                 RSurf_ActiveModelEntity(ent, false, false, false);
12012         else if (prepass)
12013                 RSurf_ActiveModelEntity(ent, true, true, true);
12014         else if (depthonly)
12015                 RSurf_ActiveModelEntity(ent, false, false, false);
12016         else
12017         {
12018                 switch (vid.renderpath)
12019                 {
12020                 case RENDERPATH_GL20:
12021                 case RENDERPATH_CGGL:
12022                         RSurf_ActiveModelEntity(ent, true, true, false);
12023                         break;
12024                 case RENDERPATH_GL13:
12025                 case RENDERPATH_GL11:
12026                         RSurf_ActiveModelEntity(ent, true, false, false);
12027                         break;
12028                 }
12029         }
12030
12031         surfaces = model->data_surfaces;
12032         update = model->brushq1.lightmapupdateflags;
12033
12034         // update light styles
12035         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12036         {
12037                 model_brush_lightstyleinfo_t *style;
12038                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12039                 {
12040                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12041                         {
12042                                 int *list = style->surfacelist;
12043                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12044                                 for (j = 0;j < style->numsurfaces;j++)
12045                                         update[list[j]] = true;
12046                         }
12047                 }
12048         }
12049
12050         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12051
12052         if (debug)
12053         {
12054                 R_DrawDebugModel();
12055                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12056                 return;
12057         }
12058
12059         f = 0;
12060         t = NULL;
12061         rsurface.uselightmaptexture = false;
12062         rsurface.texture = NULL;
12063         rsurface.rtlight = NULL;
12064         numsurfacelist = 0;
12065         // add visible surfaces to draw list
12066         for (i = 0;i < model->nummodelsurfaces;i++)
12067                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12068         // don't do anything if there were no surfaces
12069         if (!numsurfacelist)
12070         {
12071                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12072                 return;
12073         }
12074         // update lightmaps if needed
12075         if (update)
12076         {
12077                 int updated = 0;
12078                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12079                 {
12080                         if (update[j])
12081                         {
12082                                 updated++;
12083                                 R_BuildLightMap(ent, surfaces + j);
12084                         }
12085                 }
12086         }
12087         if (update)
12088                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12089                         if (update[j])
12090                                 R_BuildLightMap(ent, surfaces + j);
12091         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12092         GL_AlphaTest(false);
12093
12094         // add to stats if desired
12095         if (r_speeds.integer && !skysurfaces && !depthonly)
12096         {
12097                 r_refdef.stats.entities_surfaces += numsurfacelist;
12098                 for (j = 0;j < numsurfacelist;j++)
12099                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12100         }
12101
12102         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12103 }
12104
12105 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12106 {
12107         static texture_t texture;
12108         static msurface_t surface;
12109         const msurface_t *surfacelist = &surface;
12110
12111         // fake enough texture and surface state to render this geometry
12112
12113         texture.update_lastrenderframe = -1; // regenerate this texture
12114         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12115         texture.currentskinframe = skinframe;
12116         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12117         texture.specularscalemod = 1;
12118         texture.specularpowermod = 1;
12119
12120         surface.texture = &texture;
12121         surface.num_triangles = numtriangles;
12122         surface.num_firsttriangle = firsttriangle;
12123         surface.num_vertices = numvertices;
12124         surface.num_firstvertex = firstvertex;
12125
12126         // now render it
12127         rsurface.texture = R_GetCurrentTexture(surface.texture);
12128         rsurface.uselightmaptexture = false;
12129         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12130 }
12131
12132 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)
12133 {
12134         static msurface_t surface;
12135         const msurface_t *surfacelist = &surface;
12136
12137         // fake enough texture and surface state to render this geometry
12138
12139         surface.texture = texture;
12140         surface.num_triangles = numtriangles;
12141         surface.num_firsttriangle = firsttriangle;
12142         surface.num_vertices = numvertices;
12143         surface.num_firstvertex = firstvertex;
12144
12145         // now render it
12146         rsurface.texture = R_GetCurrentTexture(surface.texture);
12147         rsurface.uselightmaptexture = false;
12148         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12149 }