]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
UNMERGE
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
73 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
74 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
96 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
102
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
111
112 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
113 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
114
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
118
119 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
125 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
126 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
127 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
128
129 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
134
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
139
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
147
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
152
153 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
154
155 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
156
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
158
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
166 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
167
168 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
169
170 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
171
172 extern cvar_t v_glslgamma;
173
174 extern qboolean v_flipped_state;
175
176 static struct r_bloomstate_s
177 {
178         qboolean enabled;
179         qboolean hdr;
180
181         int bloomwidth, bloomheight;
182
183         int screentexturewidth, screentextureheight;
184         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
185
186         int bloomtexturewidth, bloomtextureheight;
187         rtexture_t *texture_bloom;
188
189         // arrays for rendering the screen passes
190         float screentexcoord2f[8];
191         float bloomtexcoord2f[8];
192         float offsettexcoord2f[8];
193
194         r_viewport_t viewport;
195 }
196 r_bloomstate;
197
198 r_waterstate_t r_waterstate;
199
200 /// shadow volume bsp struct with automatically growing nodes buffer
201 svbsp_t r_svbsp;
202
203 rtexture_t *r_texture_blanknormalmap;
204 rtexture_t *r_texture_white;
205 rtexture_t *r_texture_grey128;
206 rtexture_t *r_texture_black;
207 rtexture_t *r_texture_notexture;
208 rtexture_t *r_texture_whitecube;
209 rtexture_t *r_texture_normalizationcube;
210 rtexture_t *r_texture_fogattenuation;
211 rtexture_t *r_texture_gammaramps;
212 unsigned int r_texture_gammaramps_serial;
213 //rtexture_t *r_texture_fogintensity;
214
215 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
216 unsigned int r_numqueries;
217 unsigned int r_maxqueries;
218
219 typedef struct r_qwskincache_s
220 {
221         char name[MAX_QPATH];
222         skinframe_t *skinframe;
223 }
224 r_qwskincache_t;
225
226 static r_qwskincache_t *r_qwskincache;
227 static int r_qwskincache_size;
228
229 /// vertex coordinates for a quad that covers the screen exactly
230 const float r_screenvertex3f[12] =
231 {
232         0, 0, 0,
233         1, 0, 0,
234         1, 1, 0,
235         0, 1, 0
236 };
237
238 extern void R_DrawModelShadows(void);
239
240 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
241 {
242         int i;
243         for (i = 0;i < verts;i++)
244         {
245                 out[0] = in[0] * r;
246                 out[1] = in[1] * g;
247                 out[2] = in[2] * b;
248                 out[3] = in[3];
249                 in += 4;
250                 out += 4;
251         }
252 }
253
254 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
255 {
256         int i;
257         for (i = 0;i < verts;i++)
258         {
259                 out[0] = r;
260                 out[1] = g;
261                 out[2] = b;
262                 out[3] = a;
263                 out += 4;
264         }
265 }
266
267 // FIXME: move this to client?
268 void FOG_clear(void)
269 {
270         if (gamemode == GAME_NEHAHRA)
271         {
272                 Cvar_Set("gl_fogenable", "0");
273                 Cvar_Set("gl_fogdensity", "0.2");
274                 Cvar_Set("gl_fogred", "0.3");
275                 Cvar_Set("gl_foggreen", "0.3");
276                 Cvar_Set("gl_fogblue", "0.3");
277         }
278         r_refdef.fog_density = 0;
279         r_refdef.fog_red = 0;
280         r_refdef.fog_green = 0;
281         r_refdef.fog_blue = 0;
282         r_refdef.fog_alpha = 1;
283         r_refdef.fog_start = 0;
284         r_refdef.fog_end = 16384;
285         r_refdef.fog_height = 1<<30;
286         r_refdef.fog_fadedepth = 128;
287 }
288
289 static void R_BuildBlankTextures(void)
290 {
291         unsigned char data[4];
292         data[2] = 128; // normal X
293         data[1] = 128; // normal Y
294         data[0] = 255; // normal Z
295         data[3] = 128; // height
296         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
297         data[0] = 255;
298         data[1] = 255;
299         data[2] = 255;
300         data[3] = 255;
301         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
302         data[0] = 128;
303         data[1] = 128;
304         data[2] = 128;
305         data[3] = 255;
306         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
307         data[0] = 0;
308         data[1] = 0;
309         data[2] = 0;
310         data[3] = 255;
311         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
312 }
313
314 static void R_BuildNoTexture(void)
315 {
316         int x, y;
317         unsigned char pix[16][16][4];
318         // this makes a light grey/dark grey checkerboard texture
319         for (y = 0;y < 16;y++)
320         {
321                 for (x = 0;x < 16;x++)
322                 {
323                         if ((y < 8) ^ (x < 8))
324                         {
325                                 pix[y][x][0] = 128;
326                                 pix[y][x][1] = 128;
327                                 pix[y][x][2] = 128;
328                                 pix[y][x][3] = 255;
329                         }
330                         else
331                         {
332                                 pix[y][x][0] = 64;
333                                 pix[y][x][1] = 64;
334                                 pix[y][x][2] = 64;
335                                 pix[y][x][3] = 255;
336                         }
337                 }
338         }
339         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
340 }
341
342 static void R_BuildWhiteCube(void)
343 {
344         unsigned char data[6*1*1*4];
345         memset(data, 255, sizeof(data));
346         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
347 }
348
349 static void R_BuildNormalizationCube(void)
350 {
351         int x, y, side;
352         vec3_t v;
353         vec_t s, t, intensity;
354 #define NORMSIZE 64
355         unsigned char *data;
356         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
357         for (side = 0;side < 6;side++)
358         {
359                 for (y = 0;y < NORMSIZE;y++)
360                 {
361                         for (x = 0;x < NORMSIZE;x++)
362                         {
363                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
364                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
365                                 switch(side)
366                                 {
367                                 default:
368                                 case 0:
369                                         v[0] = 1;
370                                         v[1] = -t;
371                                         v[2] = -s;
372                                         break;
373                                 case 1:
374                                         v[0] = -1;
375                                         v[1] = -t;
376                                         v[2] = s;
377                                         break;
378                                 case 2:
379                                         v[0] = s;
380                                         v[1] = 1;
381                                         v[2] = t;
382                                         break;
383                                 case 3:
384                                         v[0] = s;
385                                         v[1] = -1;
386                                         v[2] = -t;
387                                         break;
388                                 case 4:
389                                         v[0] = s;
390                                         v[1] = -t;
391                                         v[2] = 1;
392                                         break;
393                                 case 5:
394                                         v[0] = -s;
395                                         v[1] = -t;
396                                         v[2] = -1;
397                                         break;
398                                 }
399                                 intensity = 127.0f / sqrt(DotProduct(v, v));
400                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
401                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
402                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
403                                 data[((side*64+y)*64+x)*4+3] = 255;
404                         }
405                 }
406         }
407         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
408         Mem_Free(data);
409 }
410
411 static void R_BuildFogTexture(void)
412 {
413         int x, b;
414 #define FOGWIDTH 256
415         unsigned char data1[FOGWIDTH][4];
416         //unsigned char data2[FOGWIDTH][4];
417         double d, r, alpha;
418
419         r_refdef.fogmasktable_start = r_refdef.fog_start;
420         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
421         r_refdef.fogmasktable_range = r_refdef.fogrange;
422         r_refdef.fogmasktable_density = r_refdef.fog_density;
423
424         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
425         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
426         {
427                 d = (x * r - r_refdef.fogmasktable_start);
428                 if(developer_extra.integer)
429                         Con_DPrintf("%f ", d);
430                 d = max(0, d);
431                 if (r_fog_exp2.integer)
432                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
433                 else
434                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
435                 if(developer_extra.integer)
436                         Con_DPrintf(" : %f ", alpha);
437                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
438                 if(developer_extra.integer)
439                         Con_DPrintf(" = %f\n", alpha);
440                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
441         }
442
443         for (x = 0;x < FOGWIDTH;x++)
444         {
445                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
446                 data1[x][0] = b;
447                 data1[x][1] = b;
448                 data1[x][2] = b;
449                 data1[x][3] = 255;
450                 //data2[x][0] = 255 - b;
451                 //data2[x][1] = 255 - b;
452                 //data2[x][2] = 255 - b;
453                 //data2[x][3] = 255;
454         }
455         if (r_texture_fogattenuation)
456         {
457                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
458                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
459         }
460         else
461         {
462                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
463                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
464         }
465 }
466
467 //=======================================================================================================================================================
468
469 static const char *builtinshaderstring =
470 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
471 "// written by Forest 'LordHavoc' Hale\n"
472 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
473 "\n"
474 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
475 "# define USEFOG\n"
476 "#endif\n"
477 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
478 "#define USELIGHTMAP\n"
479 "#endif\n"
480 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
481 "#define USEEYEVECTOR\n"
482 "#endif\n"
483 "\n"
484 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
485 "# extension GL_ARB_texture_rectangle : enable\n"
486 "#endif\n"
487 "\n"
488 "#ifdef USESHADOWMAP2D\n"
489 "# ifdef GL_EXT_gpu_shader4\n"
490 "#   extension GL_EXT_gpu_shader4 : enable\n"
491 "# endif\n"
492 "# ifdef GL_ARB_texture_gather\n"
493 "#   extension GL_ARB_texture_gather : enable\n"
494 "# else\n"
495 "#   ifdef GL_AMD_texture_texture4\n"
496 "#     extension GL_AMD_texture_texture4 : enable\n"
497 "#   endif\n"
498 "# endif\n"
499 "#endif\n"
500 "\n"
501 "#ifdef USESHADOWMAPCUBE\n"
502 "# extension GL_EXT_gpu_shader4 : enable\n"
503 "#endif\n"
504 "\n"
505 "//#ifdef USESHADOWSAMPLER\n"
506 "//# extension GL_ARB_shadow : enable\n"
507 "//#endif\n"
508 "\n"
509 "//#ifdef __GLSL_CG_DATA_TYPES\n"
510 "//# define myhalf half\n"
511 "//# define myhalf2 half2\n"
512 "//# define myhalf3 half3\n"
513 "//# define myhalf4 half4\n"
514 "//#else\n"
515 "# define myhalf float\n"
516 "# define myhalf2 vec2\n"
517 "# define myhalf3 vec3\n"
518 "# define myhalf4 vec4\n"
519 "//#endif\n"
520 "\n"
521 "#ifdef VERTEX_SHADER\n"
522 "uniform mat4 ModelViewProjectionMatrix;\n"
523 "#endif\n"
524 "\n"
525 "#ifdef MODE_DEPTH_OR_SHADOW\n"
526 "#ifdef VERTEX_SHADER\n"
527 "void main(void)\n"
528 "{\n"
529 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
530 "}\n"
531 "#endif\n"
532 "#else // !MODE_DEPTH_ORSHADOW\n"
533 "\n"
534 "\n"
535 "\n"
536 "\n"
537 "#ifdef MODE_SHOWDEPTH\n"
538 "#ifdef VERTEX_SHADER\n"
539 "void main(void)\n"
540 "{\n"
541 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
542 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
543 "}\n"
544 "#endif\n"
545 "\n"
546 "#ifdef FRAGMENT_SHADER\n"
547 "void main(void)\n"
548 "{\n"
549 "       gl_FragColor = gl_Color;\n"
550 "}\n"
551 "#endif\n"
552 "#else // !MODE_SHOWDEPTH\n"
553 "\n"
554 "\n"
555 "\n"
556 "\n"
557 "#ifdef MODE_POSTPROCESS\n"
558 "varying vec2 TexCoord1;\n"
559 "varying vec2 TexCoord2;\n"
560 "\n"
561 "#ifdef VERTEX_SHADER\n"
562 "void main(void)\n"
563 "{\n"
564 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
565 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
566 "#ifdef USEBLOOM\n"
567 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
568 "#endif\n"
569 "}\n"
570 "#endif\n"
571 "\n"
572 "#ifdef FRAGMENT_SHADER\n"
573 "uniform sampler2D Texture_First;\n"
574 "#ifdef USEBLOOM\n"
575 "uniform sampler2D Texture_Second;\n"
576 "#endif\n"
577 "#ifdef USEGAMMARAMPS\n"
578 "uniform sampler2D Texture_GammaRamps;\n"
579 "#endif\n"
580 "#ifdef USESATURATION\n"
581 "uniform float Saturation;\n"
582 "#endif\n"
583 "#ifdef USEVIEWTINT\n"
584 "uniform vec4 ViewTintColor;\n"
585 "#endif\n"
586 "//uncomment these if you want to use them:\n"
587 "uniform vec4 UserVec1;\n"
588 "// uniform vec4 UserVec2;\n"
589 "// uniform vec4 UserVec3;\n"
590 "// uniform vec4 UserVec4;\n"
591 "// uniform float ClientTime;\n"
592 "uniform vec2 PixelSize;\n"
593 "void main(void)\n"
594 "{\n"
595 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
596 "#ifdef USEBLOOM\n"
597 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
598 "#endif\n"
599 "#ifdef USEVIEWTINT\n"
600 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
601 "#endif\n"
602 "\n"
603 "#ifdef USEPOSTPROCESSING\n"
604 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
605 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
606 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
607 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
608 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
609 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
610 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
611 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
612 "#endif\n"
613 "\n"
614 "#ifdef USESATURATION\n"
615 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
616 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
617 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
618 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
619 "#endif\n"
620 "\n"
621 "#ifdef USEGAMMARAMPS\n"
622 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
623 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
624 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
625 "#endif\n"
626 "}\n"
627 "#endif\n"
628 "#else // !MODE_POSTPROCESS\n"
629 "\n"
630 "\n"
631 "\n"
632 "\n"
633 "#ifdef MODE_GENERIC\n"
634 "#ifdef USEDIFFUSE\n"
635 "varying vec2 TexCoord1;\n"
636 "#endif\n"
637 "#ifdef USESPECULAR\n"
638 "varying vec2 TexCoord2;\n"
639 "#endif\n"
640 "#ifdef VERTEX_SHADER\n"
641 "void main(void)\n"
642 "{\n"
643 "       gl_FrontColor = gl_Color;\n"
644 "#ifdef USEDIFFUSE\n"
645 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
646 "#endif\n"
647 "#ifdef USESPECULAR\n"
648 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
649 "#endif\n"
650 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
651 "}\n"
652 "#endif\n"
653 "\n"
654 "#ifdef FRAGMENT_SHADER\n"
655 "#ifdef USEDIFFUSE\n"
656 "uniform sampler2D Texture_First;\n"
657 "#endif\n"
658 "#ifdef USESPECULAR\n"
659 "uniform sampler2D Texture_Second;\n"
660 "#endif\n"
661 "\n"
662 "void main(void)\n"
663 "{\n"
664 "       gl_FragColor = gl_Color;\n"
665 "#ifdef USEDIFFUSE\n"
666 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
667 "#endif\n"
668 "\n"
669 "#ifdef USESPECULAR\n"
670 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
671 "# ifdef USECOLORMAPPING\n"
672 "       gl_FragColor *= tex2;\n"
673 "# endif\n"
674 "# ifdef USEGLOW\n"
675 "       gl_FragColor += tex2;\n"
676 "# endif\n"
677 "# ifdef USEVERTEXTEXTUREBLEND\n"
678 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
679 "# endif\n"
680 "#endif\n"
681 "}\n"
682 "#endif\n"
683 "#else // !MODE_GENERIC\n"
684 "\n"
685 "\n"
686 "\n"
687 "\n"
688 "#ifdef MODE_BLOOMBLUR\n"
689 "varying TexCoord;\n"
690 "#ifdef VERTEX_SHADER\n"
691 "void main(void)\n"
692 "{\n"
693 "       gl_FrontColor = gl_Color;\n"
694 "       TexCoord = gl_MultiTexCoord0.xy;\n"
695 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
696 "}\n"
697 "#endif\n"
698 "\n"
699 "#ifdef FRAGMENT_SHADER\n"
700 "uniform sampler2D Texture_First;\n"
701 "uniform vec4 BloomBlur_Parameters;\n"
702 "\n"
703 "void main(void)\n"
704 "{\n"
705 "       int i;\n"
706 "       vec2 tc = TexCoord;\n"
707 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
708 "       tc += BloomBlur_Parameters.xy;\n"
709 "       for (i = 1;i < SAMPLES;i++)\n"
710 "       {\n"
711 "               color += texture2D(Texture_First, tc).rgb;\n"
712 "               tc += BloomBlur_Parameters.xy;\n"
713 "       }\n"
714 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
715 "}\n"
716 "#endif\n"
717 "#else // !MODE_BLOOMBLUR\n"
718 "#ifdef MODE_REFRACTION\n"
719 "varying vec2 TexCoord;\n"
720 "varying vec4 ModelViewProjectionPosition;\n"
721 "uniform mat4 TexMatrix;\n"
722 "#ifdef VERTEX_SHADER\n"
723 "\n"
724 "void main(void)\n"
725 "{\n"
726 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
727 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
728 "       ModelViewProjectionPosition = gl_Position;\n"
729 "}\n"
730 "#endif\n"
731 "\n"
732 "#ifdef FRAGMENT_SHADER\n"
733 "uniform sampler2D Texture_Normal;\n"
734 "uniform sampler2D Texture_Refraction;\n"
735 "uniform sampler2D Texture_Reflection;\n"
736 "\n"
737 "uniform vec4 DistortScaleRefractReflect;\n"
738 "uniform vec4 ScreenScaleRefractReflect;\n"
739 "uniform vec4 ScreenCenterRefractReflect;\n"
740 "uniform vec4 RefractColor;\n"
741 "uniform vec4 ReflectColor;\n"
742 "uniform float ReflectFactor;\n"
743 "uniform float ReflectOffset;\n"
744 "\n"
745 "void main(void)\n"
746 "{\n"
747 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
748 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
749 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
750 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
751 "       // FIXME temporary hack to detect the case that the reflection\n"
752 "       // gets blackened at edges due to leaving the area that contains actual\n"
753 "       // content.\n"
754 "       // Remove this 'ack once we have a better way to stop this thing from\n"
755 "       // 'appening.\n"
756 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
757 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
758 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
759 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
760 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
761 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
762 "}\n"
763 "#endif\n"
764 "#else // !MODE_REFRACTION\n"
765 "\n"
766 "\n"
767 "\n"
768 "\n"
769 "#ifdef MODE_WATER\n"
770 "varying vec2 TexCoord;\n"
771 "varying vec3 EyeVector;\n"
772 "varying vec4 ModelViewProjectionPosition;\n"
773 "#ifdef VERTEX_SHADER\n"
774 "uniform vec3 EyePosition;\n"
775 "uniform mat4 TexMatrix;\n"
776 "\n"
777 "void main(void)\n"
778 "{\n"
779 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
780 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
781 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
782 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
783 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
784 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
785 "       ModelViewProjectionPosition = gl_Position;\n"
786 "}\n"
787 "#endif\n"
788 "\n"
789 "#ifdef FRAGMENT_SHADER\n"
790 "uniform sampler2D Texture_Normal;\n"
791 "uniform sampler2D Texture_Refraction;\n"
792 "uniform sampler2D Texture_Reflection;\n"
793 "\n"
794 "uniform vec4 DistortScaleRefractReflect;\n"
795 "uniform vec4 ScreenScaleRefractReflect;\n"
796 "uniform vec4 ScreenCenterRefractReflect;\n"
797 "uniform vec4 RefractColor;\n"
798 "uniform vec4 ReflectColor;\n"
799 "uniform float ReflectFactor;\n"
800 "uniform float ReflectOffset;\n"
801 "\n"
802 "void main(void)\n"
803 "{\n"
804 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
805 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
806 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
807 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
808 "       // FIXME temporary hack to detect the case that the reflection\n"
809 "       // gets blackened at edges due to leaving the area that contains actual\n"
810 "       // content.\n"
811 "       // Remove this 'ack once we have a better way to stop this thing from\n"
812 "       // 'appening.\n"
813 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
814 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
815 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
816 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
817 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
818 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
819 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
820 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
821 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
822 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
823 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
824 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
825 "}\n"
826 "#endif\n"
827 "#else // !MODE_WATER\n"
828 "\n"
829 "\n"
830 "\n"
831 "\n"
832 "// common definitions between vertex shader and fragment shader:\n"
833 "\n"
834 "varying vec2 TexCoord;\n"
835 "#ifdef USEVERTEXTEXTUREBLEND\n"
836 "varying vec2 TexCoord2;\n"
837 "#endif\n"
838 "#ifdef USELIGHTMAP\n"
839 "varying vec2 TexCoordLightmap;\n"
840 "#endif\n"
841 "\n"
842 "#ifdef MODE_LIGHTSOURCE\n"
843 "varying vec3 CubeVector;\n"
844 "#endif\n"
845 "\n"
846 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
847 "varying vec3 LightVector;\n"
848 "#endif\n"
849 "\n"
850 "#ifdef USEEYEVECTOR\n"
851 "varying vec3 EyeVector;\n"
852 "#endif\n"
853 "#ifdef USEFOG\n"
854 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
855 "#endif\n"
856 "\n"
857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
858 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
859 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
860 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
861 "#endif\n"
862 "\n"
863 "#ifdef USEREFLECTION\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "#endif\n"
866 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
867 "uniform vec3 LightPosition;\n"
868 "varying vec4 ModelViewPosition;\n"
869 "#endif\n"
870 "\n"
871 "#ifdef MODE_LIGHTSOURCE\n"
872 "uniform vec3 LightPosition;\n"
873 "#endif\n"
874 "uniform vec3 EyePosition;\n"
875 "#ifdef MODE_LIGHTDIRECTION\n"
876 "uniform vec3 LightDir;\n"
877 "#endif\n"
878 "uniform vec4 FogPlane;\n"
879 "\n"
880 "\n"
881 "\n"
882 "\n"
883 "\n"
884 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
885 "\n"
886 "// fragment shader specific:\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "\n"
889 "uniform sampler2D Texture_Normal;\n"
890 "uniform sampler2D Texture_Color;\n"
891 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
892 "uniform sampler2D Texture_Gloss;\n"
893 "//#endif\n"
894 "#ifdef USEGLOW\n"
895 "uniform sampler2D Texture_Glow;\n"
896 "#endif\n"
897 "#ifdef USEVERTEXTEXTUREBLEND\n"
898 "uniform sampler2D Texture_SecondaryNormal;\n"
899 "uniform sampler2D Texture_SecondaryColor;\n"
900 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
901 "uniform sampler2D Texture_SecondaryGloss;\n"
902 "//#endif\n"
903 "#ifdef USEGLOW\n"
904 "uniform sampler2D Texture_SecondaryGlow;\n"
905 "#endif\n"
906 "#endif\n"
907 "#ifdef USECOLORMAPPING\n"
908 "uniform sampler2D Texture_Pants;\n"
909 "uniform sampler2D Texture_Shirt;\n"
910 "#endif\n"
911 "#ifdef USEFOG\n"
912 "uniform sampler2D Texture_FogMask;\n"
913 "#endif\n"
914 "#ifdef USELIGHTMAP\n"
915 "uniform sampler2D Texture_Lightmap;\n"
916 "#endif\n"
917 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
918 "uniform sampler2D Texture_Deluxemap;\n"
919 "#endif\n"
920 "#ifdef USEREFLECTION\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "#endif\n"
923 "\n"
924 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
925 "uniform sampler2D Texture_ScreenDepth;\n"
926 "uniform sampler2D Texture_ScreenNormalMap;\n"
927 "#endif\n"
928 "#ifdef USEDEFERREDLIGHTMAP\n"
929 "uniform sampler2D Texture_ScreenDiffuse;\n"
930 "uniform sampler2D Texture_ScreenSpecular;\n"
931 "#endif\n"
932 "\n"
933 "uniform myhalf3 Color_Pants;\n"
934 "uniform myhalf3 Color_Shirt;\n"
935 "uniform myhalf3 FogColor;\n"
936 "\n"
937 "#ifdef USEFOG\n"
938 "uniform float FogRangeRecip;\n"
939 "uniform float FogPlaneViewDist;\n"
940 "uniform float FogHeightFade;\n"
941 "float FogVertex(void)\n"
942 "{\n"
943 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
944 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
945 "       float fogfrac;\n"
946 "#ifdef USEFOGOUTSIDE\n"
947 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
948 "#else\n"
949 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
950 "#endif\n"
951 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
952 "}\n"
953 "#endif\n"
954 "\n"
955 "#ifdef USEOFFSETMAPPING\n"
956 "uniform float OffsetMapping_Scale;\n"
957 "vec2 OffsetMapping(vec2 TexCoord)\n"
958 "{\n"
959 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
960 "       // 14 sample relief mapping: linear search and then binary search\n"
961 "       // this basically steps forward a small amount repeatedly until it finds\n"
962 "       // itself inside solid, then jitters forward and back using decreasing\n"
963 "       // amounts to find the impact\n"
964 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
965 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
966 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
967 "       vec3 RT = vec3(TexCoord, 1);\n"
968 "       OffsetVector *= 0.1;\n"
969 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
970 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
971 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
972 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
973 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
974 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
975 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
976 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
977 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
978 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
979 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
980 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
981 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
982 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
983 "       return RT.xy;\n"
984 "#else\n"
985 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
986 "       // this basically moves forward the full distance, and then backs up based\n"
987 "       // on height of samples\n"
988 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
989 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
990 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
991 "       TexCoord += OffsetVector;\n"
992 "       OffsetVector *= 0.333;\n"
993 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
994 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
995 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
996 "       return TexCoord;\n"
997 "#endif\n"
998 "}\n"
999 "#endif // USEOFFSETMAPPING\n"
1000 "\n"
1001 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1002 "uniform sampler2D Texture_Attenuation;\n"
1003 "uniform samplerCube Texture_Cube;\n"
1004 "\n"
1005 "#ifdef USESHADOWMAPRECT\n"
1006 "# ifdef USESHADOWSAMPLER\n"
1007 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1008 "# else\n"
1009 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1010 "# endif\n"
1011 "#endif\n"
1012 "\n"
1013 "#ifdef USESHADOWMAP2D\n"
1014 "# ifdef USESHADOWSAMPLER\n"
1015 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1016 "# else\n"
1017 "uniform sampler2D Texture_ShadowMap2D;\n"
1018 "# endif\n"
1019 "#endif\n"
1020 "\n"
1021 "#ifdef USESHADOWMAPVSDCT\n"
1022 "uniform samplerCube Texture_CubeProjection;\n"
1023 "#endif\n"
1024 "\n"
1025 "#ifdef USESHADOWMAPCUBE\n"
1026 "# ifdef USESHADOWSAMPLER\n"
1027 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1028 "# else\n"
1029 "uniform samplerCube Texture_ShadowMapCube;\n"
1030 "# endif\n"
1031 "#endif\n"
1032 "\n"
1033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1034 "uniform vec2 ShadowMap_TextureScale;\n"
1035 "uniform vec4 ShadowMap_Parameters;\n"
1036 "#endif\n"
1037 "\n"
1038 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1039 "# ifndef USESHADOWMAPVSDCT\n"
1040 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1041 "{\n"
1042 "       vec3 adir = abs(dir);\n"
1043 "       vec2 tc;\n"
1044 "       vec2 offset;\n"
1045 "       float ma;\n"
1046 "       if (adir.x > adir.y)\n"
1047 "       {\n"
1048 "               if (adir.x > adir.z) // X\n"
1049 "               {\n"
1050 "                       ma = adir.x;\n"
1051 "                       tc = dir.zy;\n"
1052 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1053 "               }\n"
1054 "               else // Z\n"
1055 "               {\n"
1056 "                       ma = adir.z;\n"
1057 "                       tc = dir.xy;\n"
1058 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1059 "               }\n"
1060 "       }\n"
1061 "       else\n"
1062 "       {\n"
1063 "               if (adir.y > adir.z) // Y\n"
1064 "               {\n"
1065 "                       ma = adir.y;\n"
1066 "                       tc = dir.xz;\n"
1067 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1068 "               }\n"
1069 "               else // Z\n"
1070 "               {\n"
1071 "                       ma = adir.z;\n"
1072 "                       tc = dir.xy;\n"
1073 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1074 "               }\n"
1075 "       }\n"
1076 "\n"
1077 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1078 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1079 "       stc.z += ShadowMap_Parameters.z;\n"
1080 "       return stc;\n"
1081 "}\n"
1082 "# else\n"
1083 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1084 "{\n"
1085 "       vec3 adir = abs(dir);\n"
1086 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1087 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1088 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1089 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1090 "       stc.z += ShadowMap_Parameters.z;\n"
1091 "       return stc;\n"
1092 "}\n"
1093 "# endif\n"
1094 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1095 "\n"
1096 "#ifdef USESHADOWMAPCUBE\n"
1097 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1098 "{\n"
1099 "       vec3 adir = abs(dir);\n"
1100 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1101 "}\n"
1102 "#endif\n"
1103 "\n"
1104 "# ifdef USESHADOWMAPRECT\n"
1105 "float ShadowMapCompare(vec3 dir)\n"
1106 "{\n"
1107 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1108 "       float f;\n"
1109 "#  ifdef USESHADOWSAMPLER\n"
1110 "\n"
1111 "#    ifdef USESHADOWMAPPCF\n"
1112 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1113 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1114 "#    else\n"
1115 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1116 "#    endif\n"
1117 "\n"
1118 "#  else\n"
1119 "\n"
1120 "#    ifdef USESHADOWMAPPCF\n"
1121 "#      if USESHADOWMAPPCF > 1\n"
1122 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1123 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1124 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1125 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1126 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1127 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1128 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1129 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1130 "#      else\n"
1131 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1132 "       vec2 offset = fract(shadowmaptc.xy);\n"
1133 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1134 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1135 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1136 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1137 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1138 "#      endif\n"
1139 "#    else\n"
1140 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1141 "#    endif\n"
1142 "\n"
1143 "#  endif\n"
1144 "       return f;\n"
1145 "}\n"
1146 "# endif\n"
1147 "\n"
1148 "# ifdef USESHADOWMAP2D\n"
1149 "float ShadowMapCompare(vec3 dir)\n"
1150 "{\n"
1151 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1152 "       float f;\n"
1153 "\n"
1154 "#  ifdef USESHADOWSAMPLER\n"
1155 "#    ifdef USESHADOWMAPPCF\n"
1156 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1157 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1158 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1159 "#    else\n"
1160 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1161 "#    endif\n"
1162 "#  else\n"
1163 "#    ifdef USESHADOWMAPPCF\n"
1164 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1165 "#      ifdef GL_ARB_texture_gather\n"
1166 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1167 "#      else\n"
1168 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1169 "#      endif\n"
1170 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1171 "       center *= ShadowMap_TextureScale;\n"
1172 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1173 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1174 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1175 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1176 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1177 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1178 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1179 "#     else\n"
1180 "#      ifdef GL_EXT_gpu_shader4\n"
1181 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1182 "#      else\n"
1183 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1184 "#      endif\n"
1185 "#      if USESHADOWMAPPCF > 1\n"
1186 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1187 "       center *= ShadowMap_TextureScale;\n"
1188 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1189 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1190 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1191 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1192 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1193 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1194 "#      else\n"
1195 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1196 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1197 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1198 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1199 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1200 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1201 "#      endif\n"
1202 "#     endif\n"
1203 "#    else\n"
1204 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1205 "#    endif\n"
1206 "#  endif\n"
1207 "       return f;\n"
1208 "}\n"
1209 "# endif\n"
1210 "\n"
1211 "# ifdef USESHADOWMAPCUBE\n"
1212 "float ShadowMapCompare(vec3 dir)\n"
1213 "{\n"
1214 "       // apply depth texture cubemap as light filter\n"
1215 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1216 "       float f;\n"
1217 "#  ifdef USESHADOWSAMPLER\n"
1218 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1219 "#  else\n"
1220 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1221 "#  endif\n"
1222 "       return f;\n"
1223 "}\n"
1224 "# endif\n"
1225 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1226 "#endif // FRAGMENT_SHADER\n"
1227 "\n"
1228 "\n"
1229 "\n"
1230 "\n"
1231 "#ifdef MODE_DEFERREDGEOMETRY\n"
1232 "#ifdef VERTEX_SHADER\n"
1233 "uniform mat4 TexMatrix;\n"
1234 "#ifdef USEVERTEXTEXTUREBLEND\n"
1235 "uniform mat4 BackgroundTexMatrix;\n"
1236 "#endif\n"
1237 "uniform mat4 ModelViewMatrix;\n"
1238 "void main(void)\n"
1239 "{\n"
1240 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1241 "#ifdef USEVERTEXTEXTUREBLEND\n"
1242 "       gl_FrontColor = gl_Color;\n"
1243 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1244 "#endif\n"
1245 "\n"
1246 "       // transform unnormalized eye direction into tangent space\n"
1247 "#ifdef USEOFFSETMAPPING\n"
1248 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1249 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1250 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1251 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1252 "#endif\n"
1253 "\n"
1254 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1255 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1256 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1257 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1258 "}\n"
1259 "#endif // VERTEX_SHADER\n"
1260 "\n"
1261 "#ifdef FRAGMENT_SHADER\n"
1262 "void main(void)\n"
1263 "{\n"
1264 "#ifdef USEOFFSETMAPPING\n"
1265 "       // apply offsetmapping\n"
1266 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1267 "#define TexCoord TexCoordOffset\n"
1268 "#endif\n"
1269 "\n"
1270 "#ifdef USEALPHAKILL\n"
1271 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1272 "               discard;\n"
1273 "#endif\n"
1274 "\n"
1275 "#ifdef USEVERTEXTEXTUREBLEND\n"
1276 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1277 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1278 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1279 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1280 "#endif\n"
1281 "\n"
1282 "#ifdef USEVERTEXTEXTUREBLEND\n"
1283 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1284 "#else\n"
1285 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1286 "#endif\n"
1287 "\n"
1288 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1289 "}\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1292 "\n"
1293 "\n"
1294 "\n"
1295 "\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1299 "void main(void)\n"
1300 "{\n"
1301 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1303 "}\n"
1304 "#endif // VERTEX_SHADER\n"
1305 "\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1315 "#endif\n"
1316 "uniform myhalf2 PixelToScreenTexCoord;\n"
1317 "void main(void)\n"
1318 "{\n"
1319 "       // calculate viewspace pixel position\n"
1320 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1321 "       vec3 position;\n"
1322 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1323 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1324 "       // decode viewspace pixel normal\n"
1325 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1326 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1327 "       // surfacenormal = pixel normal in viewspace\n"
1328 "       // LightVector = pixel to light in viewspace\n"
1329 "       // CubeVector = position in lightspace\n"
1330 "       // eyevector = pixel to view in viewspace\n"
1331 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1332 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1333 "#ifdef USEDIFFUSE\n"
1334 "       // calculate diffuse shading\n"
1335 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1336 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1337 "#endif\n"
1338 "#ifdef USESPECULAR\n"
1339 "       // calculate directional shading\n"
1340 "       vec3 eyevector = position * -1.0;\n"
1341 "#  ifdef USEEXACTSPECULARMATH\n"
1342 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1343 "#  else\n"
1344 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1345 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1346 "#  endif\n"
1347 "#endif\n"
1348 "\n"
1349 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1350 "       fade *= ShadowMapCompare(CubeVector);\n"
1351 "#endif\n"
1352 "\n"
1353 "#ifdef USEDIFFUSE\n"
1354 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1355 "#else\n"
1356 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1357 "#endif\n"
1358 "#ifdef USESPECULAR\n"
1359 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1360 "#else\n"
1361 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1362 "#endif\n"
1363 "\n"
1364 "# ifdef USECUBEFILTER\n"
1365 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1366 "       gl_FragData[0].rgb *= cubecolor;\n"
1367 "       gl_FragData[1].rgb *= cubecolor;\n"
1368 "# endif\n"
1369 "}\n"
1370 "#endif // FRAGMENT_SHADER\n"
1371 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1372 "\n"
1373 "\n"
1374 "\n"
1375 "\n"
1376 "#ifdef VERTEX_SHADER\n"
1377 "uniform mat4 TexMatrix;\n"
1378 "#ifdef USEVERTEXTEXTUREBLEND\n"
1379 "uniform mat4 BackgroundTexMatrix;\n"
1380 "#endif\n"
1381 "#ifdef MODE_LIGHTSOURCE\n"
1382 "uniform mat4 ModelToLight;\n"
1383 "#endif\n"
1384 "void main(void)\n"
1385 "{\n"
1386 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1387 "       gl_FrontColor = gl_Color;\n"
1388 "#endif\n"
1389 "       // copy the surface texcoord\n"
1390 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1391 "#ifdef USEVERTEXTEXTUREBLEND\n"
1392 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1393 "#endif\n"
1394 "#ifdef USELIGHTMAP\n"
1395 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1396 "#endif\n"
1397 "\n"
1398 "#ifdef MODE_LIGHTSOURCE\n"
1399 "       // transform vertex position into light attenuation/cubemap space\n"
1400 "       // (-1 to +1 across the light box)\n"
1401 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1402 "\n"
1403 "# ifdef USEDIFFUSE\n"
1404 "       // transform unnormalized light direction into tangent space\n"
1405 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1406 "       //  normalize it per pixel)\n"
1407 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1408 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1409 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1410 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1411 "# endif\n"
1412 "#endif\n"
1413 "\n"
1414 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1415 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1416 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1417 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1418 "#endif\n"
1419 "\n"
1420 "       // transform unnormalized eye direction into tangent space\n"
1421 "#ifdef USEEYEVECTOR\n"
1422 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1423 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1424 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1425 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1426 "#endif\n"
1427 "\n"
1428 "#ifdef USEFOG\n"
1429 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1430 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1431 "#endif\n"
1432 "\n"
1433 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1434 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1435 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1436 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1437 "#endif\n"
1438 "\n"
1439 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1440 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1441 "\n"
1442 "#ifdef USEREFLECTION\n"
1443 "       ModelViewProjectionPosition = gl_Position;\n"
1444 "#endif\n"
1445 "}\n"
1446 "#endif // VERTEX_SHADER\n"
1447 "\n"
1448 "\n"
1449 "\n"
1450 "\n"
1451 "#ifdef FRAGMENT_SHADER\n"
1452 "#ifdef USEDEFERREDLIGHTMAP\n"
1453 "uniform myhalf2 PixelToScreenTexCoord;\n"
1454 "uniform myhalf3 DeferredMod_Diffuse;\n"
1455 "uniform myhalf3 DeferredMod_Specular;\n"
1456 "#endif\n"
1457 "uniform myhalf3 Color_Ambient;\n"
1458 "uniform myhalf3 Color_Diffuse;\n"
1459 "uniform myhalf3 Color_Specular;\n"
1460 "uniform myhalf SpecularPower;\n"
1461 "#ifdef USEGLOW\n"
1462 "uniform myhalf3 Color_Glow;\n"
1463 "#endif\n"
1464 "uniform myhalf Alpha;\n"
1465 "#ifdef USEREFLECTION\n"
1466 "uniform vec4 DistortScaleRefractReflect;\n"
1467 "uniform vec4 ScreenScaleRefractReflect;\n"
1468 "uniform vec4 ScreenCenterRefractReflect;\n"
1469 "uniform myhalf4 ReflectColor;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTDIRECTION\n"
1472 "uniform myhalf3 LightColor;\n"
1473 "#endif\n"
1474 "#ifdef MODE_LIGHTSOURCE\n"
1475 "uniform myhalf3 LightColor;\n"
1476 "#endif\n"
1477 "void main(void)\n"
1478 "{\n"
1479 "#ifdef USEOFFSETMAPPING\n"
1480 "       // apply offsetmapping\n"
1481 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1482 "#define TexCoord TexCoordOffset\n"
1483 "#endif\n"
1484 "\n"
1485 "       // combine the diffuse textures (base, pants, shirt)\n"
1486 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1487 "#ifdef USEALPHAKILL\n"
1488 "       if (color.a < 0.5)\n"
1489 "               discard;\n"
1490 "#endif\n"
1491 "       color.a *= Alpha;\n"
1492 "#ifdef USECOLORMAPPING\n"
1493 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1494 "#endif\n"
1495 "#ifdef USEVERTEXTEXTUREBLEND\n"
1496 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1497 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1498 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1499 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1500 "       color.a = 1.0;\n"
1501 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1502 "#endif\n"
1503 "\n"
1504 "       // get the surface normal\n"
1505 "#ifdef USEVERTEXTEXTUREBLEND\n"
1506 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1507 "#else\n"
1508 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1509 "#endif\n"
1510 "\n"
1511 "       // get the material colors\n"
1512 "       myhalf3 diffusetex = color.rgb;\n"
1513 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1514 "# ifdef USEVERTEXTEXTUREBLEND\n"
1515 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1516 "# else\n"
1517 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1518 "# endif\n"
1519 "#endif\n"
1520 "\n"
1521 "\n"
1522 "\n"
1523 "\n"
1524 "#ifdef MODE_LIGHTSOURCE\n"
1525 "       // light source\n"
1526 "#ifdef USEDIFFUSE\n"
1527 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1528 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1529 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1530 "#ifdef USESPECULAR\n"
1531 "#ifdef USEEXACTSPECULARMATH\n"
1532 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1533 "#else\n"
1534 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1535 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1536 "#endif\n"
1537 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1538 "#endif\n"
1539 "#else\n"
1540 "       color.rgb = diffusetex * Color_Ambient;\n"
1541 "#endif\n"
1542 "       color.rgb *= LightColor;\n"
1543 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1544 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1545 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1546 "#endif\n"
1547 "# ifdef USECUBEFILTER\n"
1548 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1549 "# endif\n"
1550 "#endif // MODE_LIGHTSOURCE\n"
1551 "\n"
1552 "\n"
1553 "\n"
1554 "\n"
1555 "#ifdef MODE_LIGHTDIRECTION\n"
1556 "#define SHADING\n"
1557 "#ifdef USEDIFFUSE\n"
1558 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1559 "#endif\n"
1560 "#define lightcolor LightColor\n"
1561 "#endif // MODE_LIGHTDIRECTION\n"
1562 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1563 "#define SHADING\n"
1564 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1565 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1566 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1567 "       // convert modelspace light vector to tangentspace\n"
1568 "       myhalf3 lightnormal;\n"
1569 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1570 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1571 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1572 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1573 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1574 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1575 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1576 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1577 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1578 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1579 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1580 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1581 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1582 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1583 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1584 "#define SHADING\n"
1585 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1586 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1587 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1588 "#endif\n"
1589 "\n"
1590 "\n"
1591 "\n"
1592 "\n"
1593 "#ifdef MODE_LIGHTMAP\n"
1594 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1595 "#endif // MODE_LIGHTMAP\n"
1596 "#ifdef MODE_VERTEXCOLOR\n"
1597 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1598 "#endif // MODE_VERTEXCOLOR\n"
1599 "#ifdef MODE_FLATCOLOR\n"
1600 "       color.rgb = diffusetex * Color_Ambient;\n"
1601 "#endif // MODE_FLATCOLOR\n"
1602 "\n"
1603 "\n"
1604 "\n"
1605 "\n"
1606 "#ifdef SHADING\n"
1607 "# ifdef USEDIFFUSE\n"
1608 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1609 "#  ifdef USESPECULAR\n"
1610 "#   ifdef USEEXACTSPECULARMATH\n"
1611 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1612 "#   else\n"
1613 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1614 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1615 "#   endif\n"
1616 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1617 "#  else\n"
1618 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1619 "#  endif\n"
1620 "# else\n"
1621 "       color.rgb = diffusetex * Color_Ambient;\n"
1622 "# endif\n"
1623 "#endif\n"
1624 "\n"
1625 "#ifdef USEDEFERREDLIGHTMAP\n"
1626 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1627 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1628 "       color.rgb += glosstex * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1629 "#endif\n"
1630 "\n"
1631 "#ifdef USEGLOW\n"
1632 "#ifdef USEVERTEXTEXTUREBLEND\n"
1633 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1634 "#else\n"
1635 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1636 "#endif\n"
1637 "#endif\n"
1638 "\n"
1639 "#ifdef USEFOG\n"
1640 "#ifdef MODE_LIGHTSOURCE\n"
1641 "       color.rgb *= myhalf(FogVertex());\n"
1642 "#else\n"
1643 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1644 "#endif\n"
1645 "#endif\n"
1646 "\n"
1647 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1648 "#ifdef USEREFLECTION\n"
1649 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1650 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1651 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1652 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1653 "       // FIXME temporary hack to detect the case that the reflection\n"
1654 "       // gets blackened at edges due to leaving the area that contains actual\n"
1655 "       // content.\n"
1656 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1657 "       // 'appening.\n"
1658 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1659 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1660 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1661 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1662 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1663 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1664 "#endif\n"
1665 "\n"
1666 "       gl_FragColor = vec4(color);\n"
1667 "}\n"
1668 "#endif // FRAGMENT_SHADER\n"
1669 "\n"
1670 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1671 "#endif // !MODE_DEFERREDGEOMETRY\n"
1672 "#endif // !MODE_WATER\n"
1673 "#endif // !MODE_REFRACTION\n"
1674 "#endif // !MODE_BLOOMBLUR\n"
1675 "#endif // !MODE_GENERIC\n"
1676 "#endif // !MODE_POSTPROCESS\n"
1677 "#endif // !MODE_SHOWDEPTH\n"
1678 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1679 ;
1680
1681 /*
1682 =========================================================================================================================================================
1683
1684
1685
1686 =========================================================================================================================================================
1687
1688
1689
1690 =========================================================================================================================================================
1691
1692
1693
1694 =========================================================================================================================================================
1695
1696
1697
1698 =========================================================================================================================================================
1699
1700
1701
1702 =========================================================================================================================================================
1703
1704
1705
1706 =========================================================================================================================================================
1707 */
1708
1709 const char *builtincgshaderstring =
1710 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1711 "// written by Forest 'LordHavoc' Hale\n"
1712 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1713 "\n"
1714 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1715 "# define USEFOG\n"
1716 "#endif\n"
1717 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1718 "#define USELIGHTMAP\n"
1719 "#endif\n"
1720 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1721 "#define USEEYEVECTOR\n"
1722 "#endif\n"
1723 "\n"
1724 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1725 "#ifdef VERTEX_SHADER\n"
1726 "void main\n"
1727 "(\n"
1728 "float4 gl_Vertex : POSITION,\n"
1729 "uniform float4x4 ModelViewProjectionMatrix,\n"
1730 "out float4 gl_Position : POSITION\n"
1731 ")\n"
1732 "{\n"
1733 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1734 "}\n"
1735 "#endif\n"
1736 "#else // !MODE_DEPTH_ORSHADOW\n"
1737 "\n"
1738 "\n"
1739 "\n"
1740 "\n"
1741 "#ifdef MODE_SHOWDEPTH\n"
1742 "#ifdef VERTEX_SHADER\n"
1743 "void main\n"
1744 "(\n"
1745 "float4 gl_Vertex : POSITION,\n"
1746 "uniform float4x4 ModelViewProjectionMatrix,\n"
1747 "out float4 gl_Position : POSITION,\n"
1748 "out float4 gl_FrontColor : COLOR0\n"
1749 ")\n"
1750 "{\n"
1751 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1752 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1753 "}\n"
1754 "#endif\n"
1755 "\n"
1756 "#ifdef FRAGMENT_SHADER\n"
1757 "void main\n"
1758 "(\n"
1759 "float4 gl_FrontColor : COLOR0,\n"
1760 "out float4 gl_FragColor : COLOR\n"
1761 ")\n"
1762 "{\n"
1763 "       gl_FragColor = gl_FrontColor;\n"
1764 "}\n"
1765 "#endif\n"
1766 "#else // !MODE_SHOWDEPTH\n"
1767 "\n"
1768 "\n"
1769 "\n"
1770 "\n"
1771 "#ifdef MODE_POSTPROCESS\n"
1772 "\n"
1773 "#ifdef VERTEX_SHADER\n"
1774 "void main\n"
1775 "(\n"
1776 "float4 gl_Vertex : POSITION,\n"
1777 "uniform float4x4 ModelViewProjectionMatrix,\n"
1778 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1779 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1780 "out float4 gl_Position : POSITION,\n"
1781 "out float2 TexCoord1 : TEXCOORD0,\n"
1782 "out float2 TexCoord2 : TEXCOORD1\n"
1783 ")\n"
1784 "{\n"
1785 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1786 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1787 "#ifdef USEBLOOM\n"
1788 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1789 "#endif\n"
1790 "}\n"
1791 "#endif\n"
1792 "\n"
1793 "#ifdef FRAGMENT_SHADER\n"
1794 "void main\n"
1795 "(\n"
1796 "float2 TexCoord1 : TEXCOORD0,\n"
1797 "float2 TexCoord2 : TEXCOORD1,\n"
1798 "uniform sampler2D Texture_First,\n"
1799 "#ifdef USEBLOOM\n"
1800 "uniform sampler2D Texture_Second,\n"
1801 "#endif\n"
1802 "#ifdef USEGAMMARAMPS\n"
1803 "uniform sampler2D Texture_GammaRamps,\n"
1804 "#endif\n"
1805 "#ifdef USESATURATION\n"
1806 "uniform float Saturation,\n"
1807 "#endif\n"
1808 "#ifdef USEVIEWTINT\n"
1809 "uniform float4 ViewTintColor,\n"
1810 "#endif\n"
1811 "uniform float4 UserVec1,\n"
1812 "uniform float4 UserVec2,\n"
1813 "uniform float4 UserVec3,\n"
1814 "uniform float4 UserVec4,\n"
1815 "uniform float ClientTime,\n"
1816 "uniform float2 PixelSize,\n"
1817 "out float4 gl_FragColor : COLOR\n"
1818 ")\n"
1819 "{\n"
1820 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1821 "#ifdef USEBLOOM\n"
1822 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1823 "#endif\n"
1824 "#ifdef USEVIEWTINT\n"
1825 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1826 "#endif\n"
1827 "\n"
1828 "#ifdef USEPOSTPROCESSING\n"
1829 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1830 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1831 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1832 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1833 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1834 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1835 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1836 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1837 "#endif\n"
1838 "\n"
1839 "#ifdef USESATURATION\n"
1840 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1841 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1842 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1843 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1844 "#endif\n"
1845 "\n"
1846 "#ifdef USEGAMMARAMPS\n"
1847 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1848 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1849 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1850 "#endif\n"
1851 "}\n"
1852 "#endif\n"
1853 "#else // !MODE_POSTPROCESS\n"
1854 "\n"
1855 "\n"
1856 "\n"
1857 "\n"
1858 "#ifdef MODE_GENERIC\n"
1859 "#ifdef VERTEX_SHADER\n"
1860 "void main\n"
1861 "(\n"
1862 "float4 gl_Vertex : POSITION,\n"
1863 "uniform float4x4 ModelViewProjectionMatrix,\n"
1864 "float4 gl_Color : COLOR0,\n"
1865 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1866 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1867 "out float4 gl_Position : POSITION,\n"
1868 "out float4 gl_FrontColor : COLOR,\n"
1869 "out float2 TexCoord1 : TEXCOORD0,\n"
1870 "out float2 TexCoord2 : TEXCOORD1\n"
1871 ")\n"
1872 "{\n"
1873 "       gl_FrontColor = gl_Color;\n"
1874 "#ifdef USEDIFFUSE\n"
1875 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1876 "#endif\n"
1877 "#ifdef USESPECULAR\n"
1878 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1879 "#endif\n"
1880 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1881 "}\n"
1882 "#endif\n"
1883 "\n"
1884 "#ifdef FRAGMENT_SHADER\n"
1885 "\n"
1886 "void main\n"
1887 "(\n"
1888 "float4 gl_FrontColor : COLOR,\n"
1889 "float2 TexCoord1 : TEXCOORD0,\n"
1890 "float2 TexCoord2 : TEXCOORD1,\n"
1891 "#ifdef USEDIFFUSE\n"
1892 "uniform sampler2D Texture_First,\n"
1893 "#endif\n"
1894 "#ifdef USESPECULAR\n"
1895 "uniform sampler2D Texture_Second,\n"
1896 "#endif\n"
1897 "out float4 gl_FragColor : COLOR\n"
1898 ")\n"
1899 "{\n"
1900 "       gl_FragColor = gl_FrontColor;\n"
1901 "#ifdef USEDIFFUSE\n"
1902 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1903 "#endif\n"
1904 "\n"
1905 "#ifdef USESPECULAR\n"
1906 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1907 "# ifdef USECOLORMAPPING\n"
1908 "       gl_FragColor *= tex2;\n"
1909 "# endif\n"
1910 "# ifdef USEGLOW\n"
1911 "       gl_FragColor += tex2;\n"
1912 "# endif\n"
1913 "# ifdef USEVERTEXTEXTUREBLEND\n"
1914 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1915 "# endif\n"
1916 "#endif\n"
1917 "}\n"
1918 "#endif\n"
1919 "#else // !MODE_GENERIC\n"
1920 "\n"
1921 "\n"
1922 "\n"
1923 "\n"
1924 "#ifdef MODE_BLOOMBLUR\n"
1925 "#ifdef VERTEX_SHADER\n"
1926 "void main\n"
1927 "(\n"
1928 "float4 gl_Vertex : POSITION,\n"
1929 "uniform float4x4 ModelViewProjectionMatrix,\n"
1930 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1931 "out float4 gl_Position : POSITION,\n"
1932 "out float2 TexCoord : TEXCOORD0\n"
1933 ")\n"
1934 "{\n"
1935 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1936 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1937 "}\n"
1938 "#endif\n"
1939 "\n"
1940 "#ifdef FRAGMENT_SHADER\n"
1941 "\n"
1942 "void main\n"
1943 "(\n"
1944 "float2 TexCoord : TEXCOORD0,\n"
1945 "uniform sampler2D Texture_First,\n"
1946 "uniform float4 BloomBlur_Parameters,\n"
1947 "out float4 gl_FragColor : COLOR\n"
1948 ")\n"
1949 "{\n"
1950 "       int i;\n"
1951 "       float2 tc = TexCoord;\n"
1952 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1953 "       tc += BloomBlur_Parameters.xy;\n"
1954 "       for (i = 1;i < SAMPLES;i++)\n"
1955 "       {\n"
1956 "               color += tex2D(Texture_First, tc).rgb;\n"
1957 "               tc += BloomBlur_Parameters.xy;\n"
1958 "       }\n"
1959 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1960 "}\n"
1961 "#endif\n"
1962 "#else // !MODE_BLOOMBLUR\n"
1963 "#ifdef MODE_REFRACTION\n"
1964 "#ifdef VERTEX_SHADER\n"
1965 "void main\n"
1966 "(\n"
1967 "float4 gl_Vertex : POSITION,\n"
1968 "uniform float4x4 ModelViewProjectionMatrix,\n"
1969 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1970 "uniform float4x4 TexMatrix,\n"
1971 "uniform float3 EyePosition,\n"
1972 "out float4 gl_Position : POSITION,\n"
1973 "out float2 TexCoord : TEXCOORD0,\n"
1974 "out float3 EyeVector : TEXCOORD1,\n"
1975 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1976 ")\n"
1977 "{\n"
1978 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1979 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1980 "       ModelViewProjectionPosition = gl_Position;\n"
1981 "}\n"
1982 "#endif\n"
1983 "\n"
1984 "#ifdef FRAGMENT_SHADER\n"
1985 "void main\n"
1986 "(\n"
1987 "float2 TexCoord : TEXCOORD0,\n"
1988 "float3 EyeVector : TEXCOORD1,\n"
1989 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1990 "uniform sampler2D Texture_Normal,\n"
1991 "uniform sampler2D Texture_Refraction,\n"
1992 "uniform sampler2D Texture_Reflection,\n"
1993 "uniform float4 DistortScaleRefractReflect,\n"
1994 "uniform float4 ScreenScaleRefractReflect,\n"
1995 "uniform float4 ScreenCenterRefractReflect,\n"
1996 "uniform float4 RefractColor,\n"
1997 "out float4 gl_FragColor : COLOR\n"
1998 ")\n"
1999 "{\n"
2000 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2001 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2002 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2003 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2004 "       // FIXME temporary hack to detect the case that the reflection\n"
2005 "       // gets blackened at edges due to leaving the area that contains actual\n"
2006 "       // content.\n"
2007 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2008 "       // 'appening.\n"
2009 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2010 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2011 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2012 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2013 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2014 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2015 "}\n"
2016 "#endif\n"
2017 "#else // !MODE_REFRACTION\n"
2018 "\n"
2019 "\n"
2020 "\n"
2021 "\n"
2022 "#ifdef MODE_WATER\n"
2023 "#ifdef VERTEX_SHADER\n"
2024 "\n"
2025 "void main\n"
2026 "(\n"
2027 "float4 gl_Vertex : POSITION,\n"
2028 "uniform float4x4 ModelViewProjectionMatrix,\n"
2029 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2030 "uniform float4x4 TexMatrix,\n"
2031 "uniform float3 EyePosition,\n"
2032 "out float4 gl_Position : POSITION,\n"
2033 "out float2 TexCoord : TEXCOORD0,\n"
2034 "out float3 EyeVector : TEXCOORD1,\n"
2035 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2036 ")\n"
2037 "{\n"
2038 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2039 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2040 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2041 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2042 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2043 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2044 "       ModelViewProjectionPosition = gl_Position;\n"
2045 "}\n"
2046 "#endif\n"
2047 "\n"
2048 "#ifdef FRAGMENT_SHADER\n"
2049 "void main\n"
2050 "(\n"
2051 "float2 TexCoord : TEXCOORD0,\n"
2052 "float3 EyeVector : TEXCOORD1,\n"
2053 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2054 "uniform sampler2D Texture_Normal,\n"
2055 "uniform sampler2D Texture_Refraction,\n"
2056 "uniform sampler2D Texture_Reflection,\n"
2057 "uniform float4 DistortScaleRefractReflect,\n"
2058 "uniform float4 ScreenScaleRefractReflect,\n"
2059 "uniform float4 ScreenCenterRefractReflect,\n"
2060 "uniform float4 RefractColor,\n"
2061 "uniform float4 ReflectColor,\n"
2062 "uniform float ReflectFactor,\n"
2063 "uniform float ReflectOffset,\n"
2064 "out float4 gl_FragColor : COLOR\n"
2065 ")\n"
2066 "{\n"
2067 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2068 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2069 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2070 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2071 "       // FIXME temporary hack to detect the case that the reflection\n"
2072 "       // gets blackened at edges due to leaving the area that contains actual\n"
2073 "       // content.\n"
2074 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2075 "       // 'appening.\n"
2076 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2077 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2078 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2079 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2080 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2081 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2082 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2083 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2084 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2085 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2086 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2087 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2088 "}\n"
2089 "#endif\n"
2090 "#else // !MODE_WATER\n"
2091 "\n"
2092 "\n"
2093 "\n"
2094 "\n"
2095 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2096 "\n"
2097 "// fragment shader specific:\n"
2098 "#ifdef FRAGMENT_SHADER\n"
2099 "\n"
2100 "#ifdef USEFOG\n"
2101 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2102 "{\n"
2103 "       float fogfrac;\n"
2104 "#ifdef USEFOGOUTSIDE\n"
2105 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2106 "#else\n"
2107 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2108 "#endif\n"
2109 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2110 "}\n"
2111 "#endif\n"
2112 "\n"
2113 "#ifdef USEOFFSETMAPPING\n"
2114 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2115 "{\n"
2116 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2117 "       // 14 sample relief mapping: linear search and then binary search\n"
2118 "       // this basically steps forward a small amount repeatedly until it finds\n"
2119 "       // itself inside solid, then jitters forward and back using decreasing\n"
2120 "       // amounts to find the impact\n"
2121 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2122 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2123 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2124 "       float3 RT = float3(TexCoord, 1);\n"
2125 "       OffsetVector *= 0.1;\n"
2126 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2127 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2128 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2129 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2130 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2131 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2132 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2133 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2134 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2135 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2136 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2137 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2138 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2139 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2140 "       return RT.xy;\n"
2141 "#else\n"
2142 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2143 "       // this basically moves forward the full distance, and then backs up based\n"
2144 "       // on height of samples\n"
2145 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2146 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2147 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2148 "       TexCoord += OffsetVector;\n"
2149 "       OffsetVector *= 0.333;\n"
2150 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2151 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2152 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2153 "       return TexCoord;\n"
2154 "#endif\n"
2155 "}\n"
2156 "#endif // USEOFFSETMAPPING\n"
2157 "\n"
2158 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2159 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2160 "# ifndef USESHADOWMAPVSDCT\n"
2161 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2162 "{\n"
2163 "       float3 adir = abs(dir);\n"
2164 "       float2 tc;\n"
2165 "       float2 offset;\n"
2166 "       float ma;\n"
2167 "       if (adir.x > adir.y)\n"
2168 "       {\n"
2169 "               if (adir.x > adir.z) // X\n"
2170 "               {\n"
2171 "                       ma = adir.x;\n"
2172 "                       tc = dir.zy;\n"
2173 "                       offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2174 "               }\n"
2175 "               else // Z\n"
2176 "               {\n"
2177 "                       ma = adir.z;\n"
2178 "                       tc = dir.xy;\n"
2179 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2180 "               }\n"
2181 "       }\n"
2182 "       else\n"
2183 "       {\n"
2184 "               if (adir.y > adir.z) // Y\n"
2185 "               {\n"
2186 "                       ma = adir.y;\n"
2187 "                       tc = dir.xz;\n"
2188 "                       offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2189 "               }\n"
2190 "               else // Z\n"
2191 "               {\n"
2192 "                       ma = adir.z;\n"
2193 "                       tc = dir.xy;\n"
2194 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2195 "               }\n"
2196 "       }\n"
2197 "\n"
2198 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2199 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2200 "       stc.z += ShadowMap_Parameters.z;\n"
2201 "       return stc;\n"
2202 "}\n"
2203 "# else\n"
2204 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2205 "{\n"
2206 "       float3 adir = abs(dir);\n"
2207 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2208 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2209 "       float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2210 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2211 "       stc.z += ShadowMap_Parameters.z;\n"
2212 "       return stc;\n"
2213 "}\n"
2214 "# endif\n"
2215 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2216 "\n"
2217 "#ifdef USESHADOWMAPCUBE\n"
2218 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2219 "{\n"
2220 "    float3 adir = abs(dir);\n"
2221 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2222 "}\n"
2223 "#endif\n"
2224 "\n"
2225 "# ifdef USESHADOWMAPRECT\n"
2226 "#ifdef USESHADOWMAPVSDCT\n"
2227 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2228 "#else\n"
2229 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2230 "#endif\n"
2231 "{\n"
2232 "#ifdef USESHADOWMAPVSDCT\n"
2233 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2234 "#else\n"
2235 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2236 "#endif\n"
2237 "       float f;\n"
2238 "#  ifdef USESHADOWSAMPLER\n"
2239 "\n"
2240 "#    ifdef USESHADOWMAPPCF\n"
2241 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2242 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2243 "#    else\n"
2244 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2245 "#    endif\n"
2246 "\n"
2247 "#  else\n"
2248 "\n"
2249 "#    ifdef USESHADOWMAPPCF\n"
2250 "#      if USESHADOWMAPPCF > 1\n"
2251 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2252 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2253 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2254 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2255 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2256 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2257 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2258 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2259 "#      else\n"
2260 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2261 "    float2 offset = frac(shadowmaptc.xy);\n"
2262 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2263 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2264 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2265 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2266 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2267 "#      endif\n"
2268 "#    else\n"
2269 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2270 "#    endif\n"
2271 "\n"
2272 "#  endif\n"
2273 "       return f;\n"
2274 "}\n"
2275 "# endif\n"
2276 "\n"
2277 "# ifdef USESHADOWMAP2D\n"
2278 "#ifdef USESHADOWMAPVSDCT\n"
2279 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2280 "#else\n"
2281 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2282 "#endif\n"
2283 "{\n"
2284 "#ifdef USESHADOWMAPVSDCT\n"
2285 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2286 "#else\n"
2287 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2288 "#endif\n"
2289 "    float f;\n"
2290 "\n"
2291 "#  ifdef USESHADOWSAMPLER\n"
2292 "#    ifdef USESHADOWMAPPCF\n"
2293 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2294 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2295 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2296 "#    else\n"
2297 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2298 "#    endif\n"
2299 "#  else\n"
2300 "#    ifdef USESHADOWMAPPCF\n"
2301 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2302 "#      ifdef GL_ARB_texture_gather\n"
2303 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2304 "#      else\n"
2305 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2306 "#      endif\n"
2307 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2308 "    center *= ShadowMap_TextureScale;\n"
2309 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2310 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2311 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2312 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2313 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2314 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2315 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2316 "#     else\n"
2317 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2318 "#      if USESHADOWMAPPCF > 1\n"
2319 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2320 "    center *= ShadowMap_TextureScale;\n"
2321 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2322 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2323 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2324 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2325 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2326 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2327 "#      else\n"
2328 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2329 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2330 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2331 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2332 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2333 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2334 "#      endif\n"
2335 "#     endif\n"
2336 "#    else\n"
2337 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2338 "#    endif\n"
2339 "#  endif\n"
2340 "    return f;\n"
2341 "}\n"
2342 "# endif\n"
2343 "\n"
2344 "# ifdef USESHADOWMAPCUBE\n"
2345 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2346 "{\n"
2347 "    // apply depth texture cubemap as light filter\n"
2348 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2349 "    float f;\n"
2350 "#  ifdef USESHADOWSAMPLER\n"
2351 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2352 "#  else\n"
2353 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2354 "#  endif\n"
2355 "    return f;\n"
2356 "}\n"
2357 "# endif\n"
2358 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2359 "#endif // FRAGMENT_SHADER\n"
2360 "\n"
2361 "\n"
2362 "\n"
2363 "\n"
2364 "#ifdef MODE_DEFERREDGEOMETRY\n"
2365 "#ifdef VERTEX_SHADER\n"
2366 "void main\n"
2367 "(\n"
2368 "float4 gl_Vertex : POSITION,\n"
2369 "uniform float4x4 ModelViewProjectionMatrix,\n"
2370 "#ifdef USEVERTEXTEXTUREBLEND\n"
2371 "float4 gl_Color : COLOR0,\n"
2372 "#endif\n"
2373 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2374 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2375 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2376 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2377 "uniform float4x4 TexMatrix,\n"
2378 "#ifdef USEVERTEXTEXTUREBLEND\n"
2379 "uniform float4x4 BackgroundTexMatrix,\n"
2380 "#endif\n"
2381 "uniform float4x4 ModelViewMatrix,\n"
2382 "#ifdef USEOFFSETMAPPING\n"
2383 "uniform float3 EyePosition,\n"
2384 "#endif\n"
2385 "out float4 gl_Position : POSITION,\n"
2386 "out float4 gl_FrontColor : COLOR,\n"
2387 "out float4 TexCoordBoth : TEXCOORD0,\n"
2388 "#ifdef USEOFFSETMAPPING\n"
2389 "out float3 EyeVector : TEXCOORD2,\n"
2390 "#endif\n"
2391 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2392 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2393 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2394 ")\n"
2395 "{\n"
2396 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2397 "#ifdef USEVERTEXTEXTUREBLEND\n"
2398 "       gl_FrontColor = gl_Color;\n"
2399 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2400 "#endif\n"
2401 "\n"
2402 "       // transform unnormalized eye direction into tangent space\n"
2403 "#ifdef USEOFFSETMAPPING\n"
2404 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2405 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2406 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2407 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2408 "#endif\n"
2409 "\n"
2410 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2411 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2412 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2413 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2414 "}\n"
2415 "#endif // VERTEX_SHADER\n"
2416 "\n"
2417 "#ifdef FRAGMENT_SHADER\n"
2418 "void main\n"
2419 "(\n"
2420 "float4 TexCoordBoth : TEXCOORD0,\n"
2421 "float3 EyeVector : TEXCOORD2,\n"
2422 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2423 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2424 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2425 "uniform sampler2D Texture_Normal,\n"
2426 "#ifdef USEALPHAKILL\n"
2427 "uniform sampler2D Texture_Color,\n"
2428 "#endif\n"
2429 "#ifdef USEVERTEXTEXTUREBLEND\n"
2430 "uniform sampler2D Texture_SecondaryNormal,\n"
2431 "#endif\n"
2432 "#ifdef USEOFFSETMAPPING\n"
2433 "uniform float OffsetMapping_Scale,\n"
2434 "#endif\n"
2435 "uniform half SpecularPower,\n"
2436 "out float4 gl_FragColor : COLOR\n"
2437 ")\n"
2438 "{\n"
2439 "       float2 TexCoord = TexCoordBoth.xy;\n"
2440 "#ifdef USEOFFSETMAPPING\n"
2441 "       // apply offsetmapping\n"
2442 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2443 "#define TexCoord TexCoordOffset\n"
2444 "#endif\n"
2445 "\n"
2446 "#ifdef USEALPHAKILL\n"
2447 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2448 "               discard;\n"
2449 "#endif\n"
2450 "\n"
2451 "#ifdef USEVERTEXTEXTUREBLEND\n"
2452 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2453 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2454 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2455 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2456 "#endif\n"
2457 "\n"
2458 "#ifdef USEVERTEXTEXTUREBLEND\n"
2459 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2460 "#else\n"
2461 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2462 "#endif\n"
2463 "\n"
2464 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2465 "}\n"
2466 "#endif // FRAGMENT_SHADER\n"
2467 "#else // !MODE_DEFERREDGEOMETRY\n"
2468 "\n"
2469 "\n"
2470 "\n"
2471 "\n"
2472 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2473 "#ifdef VERTEX_SHADER\n"
2474 "void main\n"
2475 "(\n"
2476 "float4 gl_Vertex : POSITION,\n"
2477 "uniform float4x4 ModelViewProjectionMatrix,\n"
2478 "uniform float4x4 ModelViewMatrix,\n"
2479 "out float4 gl_Position : POSITION,\n"
2480 "out float4 ModelViewPosition : TEXCOORD0\n"
2481 ")\n"
2482 "{\n"
2483 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2484 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2485 "}\n"
2486 "#endif // VERTEX_SHADER\n"
2487 "\n"
2488 "#ifdef FRAGMENT_SHADER\n"
2489 "void main\n"
2490 "(\n"
2491 "float2 Pixel : WPOS,\n"
2492 "float4 ModelViewPosition : TEXCOORD0,\n"
2493 "uniform float4x4 ViewToLight,\n"
2494 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2495 "uniform float3 LightPosition,\n"
2496 "uniform half2 PixelToScreenTexCoord,\n"
2497 "uniform half3 DeferredColor_Ambient,\n"
2498 "uniform half3 DeferredColor_Diffuse,\n"
2499 "#ifdef USESPECULAR\n"
2500 "uniform half3 DeferredColor_Specular,\n"
2501 "uniform half SpecularPower,\n"
2502 "#endif\n"
2503 "uniform sampler2D Texture_Attenuation,\n"
2504 "uniform sampler2D Texture_ScreenDepth,\n"
2505 "uniform sampler2D Texture_ScreenNormalMap,\n"
2506 "\n"
2507 "#ifdef USESHADOWMAPRECT\n"
2508 "# ifdef USESHADOWSAMPLER\n"
2509 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2510 "# else\n"
2511 "uniform samplerRECT Texture_ShadowMapRect,\n"
2512 "# endif\n"
2513 "#endif\n"
2514 "\n"
2515 "#ifdef USESHADOWMAP2D\n"
2516 "# ifdef USESHADOWSAMPLER\n"
2517 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2518 "# else\n"
2519 "uniform sampler2D Texture_ShadowMap2D,\n"
2520 "# endif\n"
2521 "#endif\n"
2522 "\n"
2523 "#ifdef USESHADOWMAPVSDCT\n"
2524 "uniform samplerCUBE Texture_CubeProjection,\n"
2525 "#endif\n"
2526 "\n"
2527 "#ifdef USESHADOWMAPCUBE\n"
2528 "# ifdef USESHADOWSAMPLER\n"
2529 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2530 "# else\n"
2531 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2532 "# endif\n"
2533 "#endif\n"
2534 "\n"
2535 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2536 "uniform float2 ShadowMap_TextureScale,\n"
2537 "uniform float4 ShadowMap_Parameters,\n"
2538 "#endif\n"
2539 "\n"
2540 "out float4 gl_FragData0 : COLOR0,\n"
2541 "out float4 gl_FragData1 : COLOR1\n"
2542 ")\n"
2543 "{\n"
2544 "       // calculate viewspace pixel position\n"
2545 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2546 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2547 "       float3 position;\n"
2548 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2549 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2550 "       // decode viewspace pixel normal\n"
2551 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2552 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2553 "       // surfacenormal = pixel normal in viewspace\n"
2554 "       // LightVector = pixel to light in viewspace\n"
2555 "       // CubeVector = position in lightspace\n"
2556 "       // eyevector = pixel to view in viewspace\n"
2557 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2558 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2559 "#ifdef USEDIFFUSE\n"
2560 "       // calculate diffuse shading\n"
2561 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2562 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2563 "#endif\n"
2564 "#ifdef USESPECULAR\n"
2565 "       // calculate directional shading\n"
2566 "       float3 eyevector = position * -1.0;\n"
2567 "#  ifdef USEEXACTSPECULARMATH\n"
2568 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2569 "#  else\n"
2570 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2571 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2572 "#  endif\n"
2573 "#endif\n"
2574 "\n"
2575 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2576 "       fade *= ShadowMapCompare(CubeVector,\n"
2577 "# if defined(USESHADOWMAP2D)\n"
2578 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2579 "# endif\n"
2580 "# if defined(USESHADOWMAPRECT)\n"
2581 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2582 "# endif\n"
2583 "# if defined(USESHADOWMAPCUBE)\n"
2584 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2585 "# endif\n"
2586 "\n"
2587 "#ifdef USESHADOWMAPVSDCT\n"
2588 ", Texture_CubeProjection\n"
2589 "#endif\n"
2590 "       );\n"
2591 "#endif\n"
2592 "\n"
2593 "#ifdef USEDIFFUSE\n"
2594 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2595 "#else\n"
2596 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2597 "#endif\n"
2598 "#ifdef USESPECULAR\n"
2599 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2600 "#else\n"
2601 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2602 "#endif\n"
2603 "\n"
2604 "# ifdef USECUBEFILTER\n"
2605 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2606 "       gl_FragData0.rgb *= cubecolor;\n"
2607 "       gl_FragData1.rgb *= cubecolor;\n"
2608 "# endif\n"
2609 "}\n"
2610 "#endif // FRAGMENT_SHADER\n"
2611 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2612 "\n"
2613 "\n"
2614 "\n"
2615 "\n"
2616 "#ifdef VERTEX_SHADER\n"
2617 "void main\n"
2618 "(\n"
2619 "float4 gl_Vertex : POSITION,\n"
2620 "uniform float4x4 ModelViewProjectionMatrix,\n"
2621 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2622 "float4 gl_Color : COLOR0,\n"
2623 "#endif\n"
2624 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2625 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2626 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2627 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2628 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2629 "\n"
2630 "uniform float3 EyePosition,\n"
2631 "uniform float4x4 TexMatrix,\n"
2632 "#ifdef USEVERTEXTEXTUREBLEND\n"
2633 "uniform float4x4 BackgroundTexMatrix,\n"
2634 "#endif\n"
2635 "#ifdef MODE_LIGHTSOURCE\n"
2636 "uniform float4x4 ModelToLight,\n"
2637 "#endif\n"
2638 "#ifdef MODE_LIGHTSOURCE\n"
2639 "uniform float3 LightPosition,\n"
2640 "#endif\n"
2641 "#ifdef MODE_LIGHTDIRECTION\n"
2642 "uniform float3 LightDir,\n"
2643 "#endif\n"
2644 "uniform float4 FogPlane,\n"
2645 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2646 "uniform float3 LightPosition,\n"
2647 "#endif\n"
2648 "\n"
2649 "out float4 gl_FrontColor : COLOR,\n"
2650 "out float4 TexCoordBoth : TEXCOORD0,\n"
2651 "#ifdef USELIGHTMAP\n"
2652 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2653 "#endif\n"
2654 "#ifdef USEEYEVECTOR\n"
2655 "out float3 EyeVector : TEXCOORD2,\n"
2656 "#endif\n"
2657 "#ifdef USEREFLECTION\n"
2658 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2659 "#endif\n"
2660 "#ifdef USEFOG\n"
2661 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2662 "#endif\n"
2663 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2664 "out float3 LightVector : TEXCOORD5,\n"
2665 "#endif\n"
2666 "#ifdef MODE_LIGHTSOURCE\n"
2667 "out float3 CubeVector : TEXCOORD3,\n"
2668 "#endif\n"
2669 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2670 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2671 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2672 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2673 "#endif\n"
2674 "out float4 gl_Position : POSITION\n"
2675 ")\n"
2676 "{\n"
2677 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2678 "       gl_FrontColor = gl_Color;\n"
2679 "#endif\n"
2680 "       // copy the surface texcoord\n"
2681 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2682 "#ifdef USEVERTEXTEXTUREBLEND\n"
2683 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2684 "#endif\n"
2685 "#ifdef USELIGHTMAP\n"
2686 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2687 "#endif\n"
2688 "\n"
2689 "#ifdef MODE_LIGHTSOURCE\n"
2690 "       // transform vertex position into light attenuation/cubemap space\n"
2691 "       // (-1 to +1 across the light box)\n"
2692 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2693 "\n"
2694 "# ifdef USEDIFFUSE\n"
2695 "       // transform unnormalized light direction into tangent space\n"
2696 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2697 "       //  normalize it per pixel)\n"
2698 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2699 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2700 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2701 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2702 "# endif\n"
2703 "#endif\n"
2704 "\n"
2705 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2706 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2707 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2708 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2709 "#endif\n"
2710 "\n"
2711 "       // transform unnormalized eye direction into tangent space\n"
2712 "#ifdef USEEYEVECTOR\n"
2713 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2714 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2715 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2716 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2717 "#endif\n"
2718 "\n"
2719 "#ifdef USEFOG\n"
2720 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2721 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2722 "#endif\n"
2723 "\n"
2724 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2725 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2726 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2727 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2728 "#endif\n"
2729 "\n"
2730 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2731 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2732 "\n"
2733 "#ifdef USEREFLECTION\n"
2734 "       ModelViewProjectionPosition = gl_Position;\n"
2735 "#endif\n"
2736 "}\n"
2737 "#endif // VERTEX_SHADER\n"
2738 "\n"
2739 "\n"
2740 "\n"
2741 "\n"
2742 "#ifdef FRAGMENT_SHADER\n"
2743 "void main\n"
2744 "(\n"
2745 "#ifdef USEDEFERREDLIGHTMAP\n"
2746 "float2 Pixel : WPOS,\n"
2747 "#endif\n"
2748 "float4 gl_FrontColor : COLOR,\n"
2749 "float4 TexCoordBoth : TEXCOORD0,\n"
2750 "#ifdef USELIGHTMAP\n"
2751 "float2 TexCoordLightmap : TEXCOORD1,\n"
2752 "#endif\n"
2753 "#ifdef USEEYEVECTOR\n"
2754 "float3 EyeVector : TEXCOORD2,\n"
2755 "#endif\n"
2756 "#ifdef USEREFLECTION\n"
2757 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2758 "#endif\n"
2759 "#ifdef USEFOG\n"
2760 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2761 "#endif\n"
2762 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2763 "float3 LightVector : TEXCOORD5,\n"
2764 "#endif\n"
2765 "#ifdef MODE_LIGHTSOURCE\n"
2766 "float3 CubeVector : TEXCOORD3,\n"
2767 "#endif\n"
2768 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2769 "float4 ModelViewPosition : TEXCOORD0,\n"
2770 "#endif\n"
2771 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2772 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2773 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2774 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2775 "#endif\n"
2776 "\n"
2777 "uniform sampler2D Texture_Normal,\n"
2778 "uniform sampler2D Texture_Color,\n"
2779 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2780 "uniform sampler2D Texture_Gloss,\n"
2781 "#endif\n"
2782 "#ifdef USEGLOW\n"
2783 "uniform sampler2D Texture_Glow,\n"
2784 "#endif\n"
2785 "#ifdef USEVERTEXTEXTUREBLEND\n"
2786 "uniform sampler2D Texture_SecondaryNormal,\n"
2787 "uniform sampler2D Texture_SecondaryColor,\n"
2788 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2789 "uniform sampler2D Texture_SecondaryGloss,\n"
2790 "#endif\n"
2791 "#ifdef USEGLOW\n"
2792 "uniform sampler2D Texture_SecondaryGlow,\n"
2793 "#endif\n"
2794 "#endif\n"
2795 "#ifdef USECOLORMAPPING\n"
2796 "uniform sampler2D Texture_Pants,\n"
2797 "uniform sampler2D Texture_Shirt,\n"
2798 "#endif\n"
2799 "#ifdef USEFOG\n"
2800 "uniform sampler2D Texture_FogMask,\n"
2801 "#endif\n"
2802 "#ifdef USELIGHTMAP\n"
2803 "uniform sampler2D Texture_Lightmap,\n"
2804 "#endif\n"
2805 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2806 "uniform sampler2D Texture_Deluxemap,\n"
2807 "#endif\n"
2808 "#ifdef USEREFLECTION\n"
2809 "uniform sampler2D Texture_Reflection,\n"
2810 "#endif\n"
2811 "\n"
2812 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2813 "uniform sampler2D Texture_ScreenDepth,\n"
2814 "uniform sampler2D Texture_ScreenNormalMap,\n"
2815 "#endif\n"
2816 "#ifdef USEDEFERREDLIGHTMAP\n"
2817 "uniform sampler2D Texture_ScreenDiffuse,\n"
2818 "uniform sampler2D Texture_ScreenSpecular,\n"
2819 "#endif\n"
2820 "\n"
2821 "#ifdef USECOLORMAPPING\n"
2822 "uniform half3 Color_Pants,\n"
2823 "uniform half3 Color_Shirt,\n"
2824 "#endif\n"
2825 "#ifdef USEFOG\n"
2826 "uniform float3 FogColor,\n"
2827 "uniform float FogRangeRecip,\n"
2828 "uniform float FogPlaneViewDist,\n"
2829 "uniform float FogHeightFade,\n"
2830 "#endif\n"
2831 "\n"
2832 "#ifdef USEOFFSETMAPPING\n"
2833 "uniform float OffsetMapping_Scale,\n"
2834 "#endif\n"
2835 "\n"
2836 "#ifdef USEDEFERREDLIGHTMAP\n"
2837 "uniform half2 PixelToScreenTexCoord,\n"
2838 "uniform half3 DeferredMod_Diffuse,\n"
2839 "uniform half3 DeferredMod_Specular,\n"
2840 "#endif\n"
2841 "uniform half3 Color_Ambient,\n"
2842 "uniform half3 Color_Diffuse,\n"
2843 "uniform half3 Color_Specular,\n"
2844 "uniform half SpecularPower,\n"
2845 "#ifdef USEGLOW\n"
2846 "uniform half3 Color_Glow,\n"
2847 "#endif\n"
2848 "uniform half Alpha,\n"
2849 "#ifdef USEREFLECTION\n"
2850 "uniform float4 DistortScaleRefractReflect,\n"
2851 "uniform float4 ScreenScaleRefractReflect,\n"
2852 "uniform float4 ScreenCenterRefractReflect,\n"
2853 "uniform half4 ReflectColor,\n"
2854 "#endif\n"
2855 "#ifdef MODE_LIGHTDIRECTION\n"
2856 "uniform half3 LightColor,\n"
2857 "#endif\n"
2858 "#ifdef MODE_LIGHTSOURCE\n"
2859 "uniform half3 LightColor,\n"
2860 "#endif\n"
2861 "\n"
2862 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2863 "uniform sampler2D Texture_Attenuation,\n"
2864 "uniform samplerCUBE Texture_Cube,\n"
2865 "\n"
2866 "#ifdef USESHADOWMAPRECT\n"
2867 "# ifdef USESHADOWSAMPLER\n"
2868 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2869 "# else\n"
2870 "uniform samplerRECT Texture_ShadowMapRect,\n"
2871 "# endif\n"
2872 "#endif\n"
2873 "\n"
2874 "#ifdef USESHADOWMAP2D\n"
2875 "# ifdef USESHADOWSAMPLER\n"
2876 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2877 "# else\n"
2878 "uniform sampler2D Texture_ShadowMap2D,\n"
2879 "# endif\n"
2880 "#endif\n"
2881 "\n"
2882 "#ifdef USESHADOWMAPVSDCT\n"
2883 "uniform samplerCUBE Texture_CubeProjection,\n"
2884 "#endif\n"
2885 "\n"
2886 "#ifdef USESHADOWMAPCUBE\n"
2887 "# ifdef USESHADOWSAMPLER\n"
2888 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2889 "# else\n"
2890 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2891 "# endif\n"
2892 "#endif\n"
2893 "\n"
2894 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2895 "uniform float2 ShadowMap_TextureScale,\n"
2896 "uniform float4 ShadowMap_Parameters,\n"
2897 "#endif\n"
2898 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2899 "\n"
2900 "out float4 gl_FragColor : COLOR\n"
2901 ")\n"
2902 "{\n"
2903 "       float2 TexCoord = TexCoordBoth.xy;\n"
2904 "#ifdef USEVERTEXTEXTUREBLEND\n"
2905 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2906 "#endif\n"
2907 "#ifdef USEOFFSETMAPPING\n"
2908 "       // apply offsetmapping\n"
2909 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2910 "#define TexCoord TexCoordOffset\n"
2911 "#endif\n"
2912 "\n"
2913 "       // combine the diffuse textures (base, pants, shirt)\n"
2914 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2915 "#ifdef USEALPHAKILL\n"
2916 "       if (color.a < 0.5)\n"
2917 "               discard;\n"
2918 "#endif\n"
2919 "       color.a *= Alpha;\n"
2920 "#ifdef USECOLORMAPPING\n"
2921 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2922 "#endif\n"
2923 "#ifdef USEVERTEXTEXTUREBLEND\n"
2924 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2925 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2926 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2927 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2928 "       color.a = 1.0;\n"
2929 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2930 "#endif\n"
2931 "\n"
2932 "       // get the surface normal\n"
2933 "#ifdef USEVERTEXTEXTUREBLEND\n"
2934 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2935 "#else\n"
2936 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2937 "#endif\n"
2938 "\n"
2939 "       // get the material colors\n"
2940 "       half3 diffusetex = color.rgb;\n"
2941 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2942 "# ifdef USEVERTEXTEXTUREBLEND\n"
2943 "       half3 glosstex = half3(lerp(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2944 "# else\n"
2945 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2946 "# endif\n"
2947 "#endif\n"
2948 "\n"
2949 "\n"
2950 "\n"
2951 "\n"
2952 "#ifdef MODE_LIGHTSOURCE\n"
2953 "       // light source\n"
2954 "#ifdef USEDIFFUSE\n"
2955 "       half3 lightnormal = half3(normalize(LightVector));\n"
2956 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2957 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2958 "#ifdef USESPECULAR\n"
2959 "#ifdef USEEXACTSPECULARMATH\n"
2960 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2961 "#else\n"
2962 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2963 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2964 "#endif\n"
2965 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2966 "#endif\n"
2967 "#else\n"
2968 "       color.rgb = diffusetex * Color_Ambient;\n"
2969 "#endif\n"
2970 "       color.rgb *= LightColor;\n"
2971 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2972 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2973 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2974 "# if defined(USESHADOWMAP2D)\n"
2975 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2976 "# endif\n"
2977 "# if defined(USESHADOWMAPRECT)\n"
2978 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2979 "# endif\n"
2980 "# if defined(USESHADOWMAPCUBE)\n"
2981 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2982 "# endif\n"
2983 "\n"
2984 "#ifdef USESHADOWMAPVSDCT\n"
2985 ", Texture_CubeProjection\n"
2986 "#endif\n"
2987 "       );\n"
2988 "\n"
2989 "#endif\n"
2990 "# ifdef USECUBEFILTER\n"
2991 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2992 "# endif\n"
2993 "#endif // MODE_LIGHTSOURCE\n"
2994 "\n"
2995 "\n"
2996 "\n"
2997 "\n"
2998 "#ifdef MODE_LIGHTDIRECTION\n"
2999 "#define SHADING\n"
3000 "#ifdef USEDIFFUSE\n"
3001 "       half3 lightnormal = half3(normalize(LightVector));\n"
3002 "#endif\n"
3003 "#define lightcolor LightColor\n"
3004 "#endif // MODE_LIGHTDIRECTION\n"
3005 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3006 "#define SHADING\n"
3007 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3008 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3009 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3010 "       // convert modelspace light vector to tangentspace\n"
3011 "       half3 lightnormal;\n"
3012 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3013 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3014 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3015 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3016 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3017 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3018 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3019 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3020 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3021 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3022 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3023 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3024 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3025 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3026 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3027 "#define SHADING\n"
3028 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3029 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3030 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3031 "#endif\n"
3032 "\n"
3033 "\n"
3034 "\n"
3035 "\n"
3036 "#ifdef MODE_LIGHTMAP\n"
3037 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3038 "#endif // MODE_LIGHTMAP\n"
3039 "#ifdef MODE_VERTEXCOLOR\n"
3040 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3041 "#endif // MODE_VERTEXCOLOR\n"
3042 "#ifdef MODE_FLATCOLOR\n"
3043 "       color.rgb = diffusetex * Color_Ambient;\n"
3044 "#endif // MODE_FLATCOLOR\n"
3045 "\n"
3046 "\n"
3047 "\n"
3048 "\n"
3049 "#ifdef SHADING\n"
3050 "# ifdef USEDIFFUSE\n"
3051 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3052 "#  ifdef USESPECULAR\n"
3053 "#   ifdef USEEXACTSPECULARMATH\n"
3054 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3055 "#   else\n"
3056 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3057 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3058 "#   endif\n"
3059 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3060 "#  else\n"
3061 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3062 "#  endif\n"
3063 "# else\n"
3064 "       color.rgb = diffusetex * Color_Ambient;\n"
3065 "# endif\n"
3066 "#endif\n"
3067 "\n"
3068 "#ifdef USEDEFERREDLIGHTMAP\n"
3069 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3070 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3071 "       color.rgb += glosstex * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3072 "#endif\n"
3073 "\n"
3074 "#ifdef USEGLOW\n"
3075 "#ifdef USEVERTEXTEXTUREBLEND\n"
3076 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3077 "#else\n"
3078 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3079 "#endif\n"
3080 "#endif\n"
3081 "\n"
3082 "#ifdef USEFOG\n"
3083 "#ifdef MODE_LIGHTSOURCE\n"
3084 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3085 "#else\n"
3086 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3087 "#endif\n"
3088 "#endif\n"
3089 "\n"
3090 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3091 "#ifdef USEREFLECTION\n"
3092 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3093 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3094 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3095 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3096 "       // FIXME temporary hack to detect the case that the reflection\n"
3097 "       // gets blackened at edges due to leaving the area that contains actual\n"
3098 "       // content.\n"
3099 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3100 "       // 'appening.\n"
3101 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3102 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3103 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3104 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3105 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3106 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3107 "#endif\n"
3108 "\n"
3109 "       gl_FragColor = float4(color);\n"
3110 "}\n"
3111 "#endif // FRAGMENT_SHADER\n"
3112 "\n"
3113 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3114 "#endif // !MODE_DEFERREDGEOMETRY\n"
3115 "#endif // !MODE_WATER\n"
3116 "#endif // !MODE_REFRACTION\n"
3117 "#endif // !MODE_BLOOMBLUR\n"
3118 "#endif // !MODE_GENERIC\n"
3119 "#endif // !MODE_POSTPROCESS\n"
3120 "#endif // !MODE_SHOWDEPTH\n"
3121 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3122 ;
3123
3124 //=======================================================================================================================================================
3125
3126 typedef struct shaderpermutationinfo_s
3127 {
3128         const char *pretext;
3129         const char *name;
3130 }
3131 shaderpermutationinfo_t;
3132
3133 typedef struct shadermodeinfo_s
3134 {
3135         const char *vertexfilename;
3136         const char *geometryfilename;
3137         const char *fragmentfilename;
3138         const char *pretext;
3139         const char *name;
3140 }
3141 shadermodeinfo_t;
3142
3143 typedef enum shaderpermutation_e
3144 {
3145         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3146         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3147         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3148         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3149         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3150         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3151         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3152         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3153         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3154         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3155         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3156         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3157         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3158         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3159         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3160         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3161         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3162         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3163         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3164         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3165         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3166         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3167         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3168         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3169         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3170         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3171         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3172         SHADERPERMUTATION_COUNT = 26 ///< size of shaderpermutationinfo array
3173 }
3174 shaderpermutation_t;
3175
3176 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3177 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3178 {
3179         {"#define USEDIFFUSE\n", " diffuse"},
3180         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3181         {"#define USEVIEWTINT\n", " viewtint"},
3182         {"#define USECOLORMAPPING\n", " colormapping"},
3183         {"#define USESATURATION\n", " saturation"},
3184         {"#define USEFOGINSIDE\n", " foginside"},
3185         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3186         {"#define USEGAMMARAMPS\n", " gammaramps"},
3187         {"#define USECUBEFILTER\n", " cubefilter"},
3188         {"#define USEGLOW\n", " glow"},
3189         {"#define USEBLOOM\n", " bloom"},
3190         {"#define USESPECULAR\n", " specular"},
3191         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3192         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3193         {"#define USEREFLECTION\n", " reflection"},
3194         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3195         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3196         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3197         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3198         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3199         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3200         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3201         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3202         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3203         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3204         {"#define USEALPHAKILL\n", " alphakill"},
3205 };
3206
3207 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3208 typedef enum shadermode_e
3209 {
3210         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3211         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3212         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3213         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3214         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3215         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3216         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3217         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3218         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3219         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3220         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3221         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3222         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3223         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3224         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3225         SHADERMODE_COUNT
3226 }
3227 shadermode_t;
3228
3229 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3230 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3231 {
3232         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3233         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3234         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3235         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3236         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3237         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3238         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3239         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3240         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3241         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3242         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3243         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3244         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3245         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3246         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3247 };
3248
3249 #ifdef SUPPORTCG
3250 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3251 {
3252         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3253         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3254         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3255         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3256         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3257         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3258         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3259         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3260         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3261         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3262         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3263         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3264         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3265         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3266         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3267 };
3268 #endif
3269
3270 struct r_glsl_permutation_s;
3271 typedef struct r_glsl_permutation_s
3272 {
3273         /// hash lookup data
3274         struct r_glsl_permutation_s *hashnext;
3275         unsigned int mode;
3276         unsigned int permutation;
3277
3278         /// indicates if we have tried compiling this permutation already
3279         qboolean compiled;
3280         /// 0 if compilation failed
3281         int program;
3282         /// locations of detected uniforms in program object, or -1 if not found
3283         int loc_Texture_First;
3284         int loc_Texture_Second;
3285         int loc_Texture_GammaRamps;
3286         int loc_Texture_Normal;
3287         int loc_Texture_Color;
3288         int loc_Texture_Gloss;
3289         int loc_Texture_Glow;
3290         int loc_Texture_SecondaryNormal;
3291         int loc_Texture_SecondaryColor;
3292         int loc_Texture_SecondaryGloss;
3293         int loc_Texture_SecondaryGlow;
3294         int loc_Texture_Pants;
3295         int loc_Texture_Shirt;
3296         int loc_Texture_FogMask;
3297         int loc_Texture_Lightmap;
3298         int loc_Texture_Deluxemap;
3299         int loc_Texture_Attenuation;
3300         int loc_Texture_Cube;
3301         int loc_Texture_Refraction;
3302         int loc_Texture_Reflection;
3303         int loc_Texture_ShadowMapRect;
3304         int loc_Texture_ShadowMapCube;
3305         int loc_Texture_ShadowMap2D;
3306         int loc_Texture_CubeProjection;
3307         int loc_Texture_ScreenDepth;
3308         int loc_Texture_ScreenNormalMap;
3309         int loc_Texture_ScreenDiffuse;
3310         int loc_Texture_ScreenSpecular;
3311         int loc_Alpha;
3312         int loc_BloomBlur_Parameters;
3313         int loc_ClientTime;
3314         int loc_Color_Ambient;
3315         int loc_Color_Diffuse;
3316         int loc_Color_Specular;
3317         int loc_Color_Glow;
3318         int loc_Color_Pants;
3319         int loc_Color_Shirt;
3320         int loc_DeferredColor_Ambient;
3321         int loc_DeferredColor_Diffuse;
3322         int loc_DeferredColor_Specular;
3323         int loc_DeferredMod_Diffuse;
3324         int loc_DeferredMod_Specular;
3325         int loc_DistortScaleRefractReflect;
3326         int loc_EyePosition;
3327         int loc_FogColor;
3328         int loc_FogHeightFade;
3329         int loc_FogPlane;
3330         int loc_FogPlaneViewDist;
3331         int loc_FogRangeRecip;
3332         int loc_LightColor;
3333         int loc_LightDir;
3334         int loc_LightPosition;
3335         int loc_OffsetMapping_Scale;
3336         int loc_PixelSize;
3337         int loc_ReflectColor;
3338         int loc_ReflectFactor;
3339         int loc_ReflectOffset;
3340         int loc_RefractColor;
3341         int loc_Saturation;
3342         int loc_ScreenCenterRefractReflect;
3343         int loc_ScreenScaleRefractReflect;
3344         int loc_ScreenToDepth;
3345         int loc_ShadowMap_Parameters;
3346         int loc_ShadowMap_TextureScale;
3347         int loc_SpecularPower;
3348         int loc_UserVec1;
3349         int loc_UserVec2;
3350         int loc_UserVec3;
3351         int loc_UserVec4;
3352         int loc_ViewTintColor;
3353         int loc_ViewToLight;
3354         int loc_ModelToLight;
3355         int loc_TexMatrix;
3356         int loc_BackgroundTexMatrix;
3357         int loc_ModelViewProjectionMatrix;
3358         int loc_ModelViewMatrix;
3359         int loc_PixelToScreenTexCoord;
3360 }
3361 r_glsl_permutation_t;
3362
3363 #define SHADERPERMUTATION_HASHSIZE 256
3364
3365 /// information about each possible shader permutation
3366 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3367 /// currently selected permutation
3368 r_glsl_permutation_t *r_glsl_permutation;
3369 /// storage for permutations linked in the hash table
3370 memexpandablearray_t r_glsl_permutationarray;
3371
3372 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3373 {
3374         //unsigned int hashdepth = 0;
3375         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3376         r_glsl_permutation_t *p;
3377         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3378         {
3379                 if (p->mode == mode && p->permutation == permutation)
3380                 {
3381                         //if (hashdepth > 10)
3382                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3383                         return p;
3384                 }
3385                 //hashdepth++;
3386         }
3387         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3388         p->mode = mode;
3389         p->permutation = permutation;
3390         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3391         r_glsl_permutationhash[mode][hashindex] = p;
3392         //if (hashdepth > 10)
3393         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3394         return p;
3395 }
3396
3397 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3398 {
3399         char *shaderstring;
3400         if (!filename || !filename[0])
3401                 return NULL;
3402         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3403         if (shaderstring)
3404         {
3405                 if (printfromdisknotice)
3406                         Con_DPrintf("from disk %s... ", filename);
3407                 return shaderstring;
3408         }
3409         else if (!strcmp(filename, "glsl/default.glsl"))
3410         {
3411                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3412                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3413         }
3414         return shaderstring;
3415 }
3416
3417 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3418 {
3419         int i;
3420         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3421         int vertstrings_count = 0;
3422         int geomstrings_count = 0;
3423         int fragstrings_count = 0;
3424         char *vertexstring, *geometrystring, *fragmentstring;
3425         const char *vertstrings_list[32+3];
3426         const char *geomstrings_list[32+3];
3427         const char *fragstrings_list[32+3];
3428         char permutationname[256];
3429
3430         if (p->compiled)
3431                 return;
3432         p->compiled = true;
3433         p->program = 0;
3434
3435         permutationname[0] = 0;
3436         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3437         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3438         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3439
3440         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3441
3442         // the first pretext is which type of shader to compile as
3443         // (later these will all be bound together as a program object)
3444         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3445         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3446         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3447
3448         // the second pretext is the mode (for example a light source)
3449         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3450         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3451         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3452         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3453
3454         // now add all the permutation pretexts
3455         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3456         {
3457                 if (permutation & (1<<i))
3458                 {
3459                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3460                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3461                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3462                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3463                 }
3464                 else
3465                 {
3466                         // keep line numbers correct
3467                         vertstrings_list[vertstrings_count++] = "\n";
3468                         geomstrings_list[geomstrings_count++] = "\n";
3469                         fragstrings_list[fragstrings_count++] = "\n";
3470                 }
3471         }
3472
3473         // now append the shader text itself
3474         vertstrings_list[vertstrings_count++] = vertexstring;
3475         geomstrings_list[geomstrings_count++] = geometrystring;
3476         fragstrings_list[fragstrings_count++] = fragmentstring;
3477
3478         // if any sources were NULL, clear the respective list
3479         if (!vertexstring)
3480                 vertstrings_count = 0;
3481         if (!geometrystring)
3482                 geomstrings_count = 0;
3483         if (!fragmentstring)
3484                 fragstrings_count = 0;
3485
3486         // compile the shader program
3487         if (vertstrings_count + geomstrings_count + fragstrings_count)
3488                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3489         if (p->program)
3490         {
3491                 CHECKGLERROR
3492                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3493                 // look up all the uniform variable names we care about, so we don't
3494                 // have to look them up every time we set them
3495
3496                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3497                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3498                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3499                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3500                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3501                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3502                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3503                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3504                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3505                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3506                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3507                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3508                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3509                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3510                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3511                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3512                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3513                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3514                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3515                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3516                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3517                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3518                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3519                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3520                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3521                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3522                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3523                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3524                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3525                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3526                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3527                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3528                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3529                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3530                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3531                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3532                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3533                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3534                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3535                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3536                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3537                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3538                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3539                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3540                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3541                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3542                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3543                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3544                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3545                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3546                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3547                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3548                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3549                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3550                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3551                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3552                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3553                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3554                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3555                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3556                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3557                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3558                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3559                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3560                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3561                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3562                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3563                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3564                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3565                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3566                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3567                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3568                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3569                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3570                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3571                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3572                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3573                 // initialize the samplers to refer to the texture units we use
3574                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3575                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3576                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3577                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3578                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3579                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3580                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3581                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3582                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3583                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3584                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3585                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3586                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3587                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3588                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3589                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3590                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3591                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3592                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3593                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3594                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3595                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3596                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3597                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3598                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3599                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3600                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3601                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3602                 CHECKGLERROR
3603                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3604         }
3605         else
3606                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3607
3608         // free the strings
3609         if (vertexstring)
3610                 Mem_Free(vertexstring);
3611         if (geometrystring)
3612                 Mem_Free(geometrystring);
3613         if (fragmentstring)
3614                 Mem_Free(fragmentstring);
3615 }
3616
3617 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3618 {
3619         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3620         if (r_glsl_permutation != perm)
3621         {
3622                 r_glsl_permutation = perm;
3623                 if (!r_glsl_permutation->program)
3624                 {
3625                         if (!r_glsl_permutation->compiled)
3626                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3627                         if (!r_glsl_permutation->program)
3628                         {
3629                                 // remove features until we find a valid permutation
3630                                 int i;
3631                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3632                                 {
3633                                         // reduce i more quickly whenever it would not remove any bits
3634                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3635                                         if (!(permutation & j))
3636                                                 continue;
3637                                         permutation -= j;
3638                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3639                                         if (!r_glsl_permutation->compiled)
3640                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3641                                         if (r_glsl_permutation->program)
3642                                                 break;
3643                                 }
3644                                 if (i >= SHADERPERMUTATION_COUNT)
3645                                 {
3646                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3647                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3648                                         qglUseProgramObjectARB(0);CHECKGLERROR
3649                                         return; // no bit left to clear, entire mode is broken
3650                                 }
3651                         }
3652                 }
3653                 CHECKGLERROR
3654                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3655         }
3656         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3657         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3658 }
3659
3660 #ifdef SUPPORTCG
3661 #include <Cg/cgGL.h>
3662 struct r_cg_permutation_s;
3663 typedef struct r_cg_permutation_s
3664 {
3665         /// hash lookup data
3666         struct r_cg_permutation_s *hashnext;
3667         unsigned int mode;
3668         unsigned int permutation;
3669
3670         /// indicates if we have tried compiling this permutation already
3671         qboolean compiled;
3672         /// 0 if compilation failed
3673         CGprogram vprogram;
3674         CGprogram fprogram;
3675         /// locations of detected parameters in programs, or NULL if not found
3676         CGparameter vp_EyePosition;
3677         CGparameter vp_FogPlane;
3678         CGparameter vp_LightDir;
3679         CGparameter vp_LightPosition;
3680         CGparameter vp_ModelToLight;
3681         CGparameter vp_TexMatrix;
3682         CGparameter vp_BackgroundTexMatrix;
3683         CGparameter vp_ModelViewProjectionMatrix;
3684         CGparameter vp_ModelViewMatrix;
3685
3686         CGparameter fp_Texture_First;
3687         CGparameter fp_Texture_Second;
3688         CGparameter fp_Texture_GammaRamps;
3689         CGparameter fp_Texture_Normal;
3690         CGparameter fp_Texture_Color;
3691         CGparameter fp_Texture_Gloss;
3692         CGparameter fp_Texture_Glow;
3693         CGparameter fp_Texture_SecondaryNormal;
3694         CGparameter fp_Texture_SecondaryColor;
3695         CGparameter fp_Texture_SecondaryGloss;
3696         CGparameter fp_Texture_SecondaryGlow;
3697         CGparameter fp_Texture_Pants;
3698         CGparameter fp_Texture_Shirt;
3699         CGparameter fp_Texture_FogMask;
3700         CGparameter fp_Texture_Lightmap;
3701         CGparameter fp_Texture_Deluxemap;
3702         CGparameter fp_Texture_Attenuation;
3703         CGparameter fp_Texture_Cube;
3704         CGparameter fp_Texture_Refraction;
3705         CGparameter fp_Texture_Reflection;
3706         CGparameter fp_Texture_ShadowMapRect;
3707         CGparameter fp_Texture_ShadowMapCube;
3708         CGparameter fp_Texture_ShadowMap2D;
3709         CGparameter fp_Texture_CubeProjection;
3710         CGparameter fp_Texture_ScreenDepth;
3711         CGparameter fp_Texture_ScreenNormalMap;
3712         CGparameter fp_Texture_ScreenDiffuse;
3713         CGparameter fp_Texture_ScreenSpecular;
3714         CGparameter fp_Alpha;
3715         CGparameter fp_BloomBlur_Parameters;
3716         CGparameter fp_ClientTime;
3717         CGparameter fp_Color_Ambient;
3718         CGparameter fp_Color_Diffuse;
3719         CGparameter fp_Color_Specular;
3720         CGparameter fp_Color_Glow;
3721         CGparameter fp_Color_Pants;
3722         CGparameter fp_Color_Shirt;
3723         CGparameter fp_DeferredColor_Ambient;
3724         CGparameter fp_DeferredColor_Diffuse;
3725         CGparameter fp_DeferredColor_Specular;
3726         CGparameter fp_DeferredMod_Diffuse;
3727         CGparameter fp_DeferredMod_Specular;
3728         CGparameter fp_DistortScaleRefractReflect;
3729         CGparameter fp_EyePosition;
3730         CGparameter fp_FogColor;
3731         CGparameter fp_FogHeightFade;
3732         CGparameter fp_FogPlane;
3733         CGparameter fp_FogPlaneViewDist;
3734         CGparameter fp_FogRangeRecip;
3735         CGparameter fp_LightColor;
3736         CGparameter fp_LightDir;
3737         CGparameter fp_LightPosition;
3738         CGparameter fp_OffsetMapping_Scale;
3739         CGparameter fp_PixelSize;
3740         CGparameter fp_ReflectColor;
3741         CGparameter fp_ReflectFactor;
3742         CGparameter fp_ReflectOffset;
3743         CGparameter fp_RefractColor;
3744         CGparameter fp_Saturation;
3745         CGparameter fp_ScreenCenterRefractReflect;
3746         CGparameter fp_ScreenScaleRefractReflect;
3747         CGparameter fp_ScreenToDepth;
3748         CGparameter fp_ShadowMap_Parameters;
3749         CGparameter fp_ShadowMap_TextureScale;
3750         CGparameter fp_SpecularPower;
3751         CGparameter fp_UserVec1;
3752         CGparameter fp_UserVec2;
3753         CGparameter fp_UserVec3;
3754         CGparameter fp_UserVec4;
3755         CGparameter fp_ViewTintColor;
3756         CGparameter fp_ViewToLight;
3757         CGparameter fp_PixelToScreenTexCoord;
3758 }
3759 r_cg_permutation_t;
3760
3761 /// information about each possible shader permutation
3762 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3763 /// currently selected permutation
3764 r_cg_permutation_t *r_cg_permutation;
3765 /// storage for permutations linked in the hash table
3766 memexpandablearray_t r_cg_permutationarray;
3767
3768 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
3769
3770 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3771 {
3772         //unsigned int hashdepth = 0;
3773         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3774         r_cg_permutation_t *p;
3775         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3776         {
3777                 if (p->mode == mode && p->permutation == permutation)
3778                 {
3779                         //if (hashdepth > 10)
3780                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3781                         return p;
3782                 }
3783                 //hashdepth++;
3784         }
3785         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3786         p->mode = mode;
3787         p->permutation = permutation;
3788         p->hashnext = r_cg_permutationhash[mode][hashindex];
3789         r_cg_permutationhash[mode][hashindex] = p;
3790         //if (hashdepth > 10)
3791         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3792         return p;
3793 }
3794
3795 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3796 {
3797         char *shaderstring;
3798         if (!filename || !filename[0])
3799                 return NULL;
3800         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3801         if (shaderstring)
3802         {
3803                 if (printfromdisknotice)
3804                         Con_DPrintf("from disk %s... ", filename);
3805                 return shaderstring;
3806         }
3807         else if (!strcmp(filename, "cg/default.cg"))
3808         {
3809                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3810                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3811         }
3812         return shaderstring;
3813 }
3814
3815 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3816 {
3817         int i;
3818         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3819         int vertstrings_count = 0, vertstring_length = 0;
3820         int geomstrings_count = 0, geomstring_length = 0;
3821         int fragstrings_count = 0, fragstring_length = 0;
3822         char *t;
3823         char *vertexstring, *geometrystring, *fragmentstring;
3824         char *vertstring, *geomstring, *fragstring;
3825         const char *vertstrings_list[32+3];
3826         const char *geomstrings_list[32+3];
3827         const char *fragstrings_list[32+3];
3828         char permutationname[256];
3829         CGprofile vertexProfile;
3830         CGprofile fragmentProfile;
3831
3832         if (p->compiled)
3833                 return;
3834         p->compiled = true;
3835         p->vprogram = NULL;
3836         p->fprogram = NULL;
3837
3838         permutationname[0] = 0;
3839         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3840         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3841         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3842
3843         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3844
3845         // the first pretext is which type of shader to compile as
3846         // (later these will all be bound together as a program object)
3847         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3848         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3849         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3850
3851         // the second pretext is the mode (for example a light source)
3852         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3853         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3854         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3855         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3856
3857         // now add all the permutation pretexts
3858         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3859         {
3860                 if (permutation & (1<<i))
3861                 {
3862                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3863                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3864                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3865                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3866                 }
3867                 else
3868                 {
3869                         // keep line numbers correct
3870                         vertstrings_list[vertstrings_count++] = "\n";
3871                         geomstrings_list[geomstrings_count++] = "\n";
3872                         fragstrings_list[fragstrings_count++] = "\n";
3873                 }
3874         }
3875
3876         // now append the shader text itself
3877         vertstrings_list[vertstrings_count++] = vertexstring;
3878         geomstrings_list[geomstrings_count++] = geometrystring;
3879         fragstrings_list[fragstrings_count++] = fragmentstring;
3880
3881         // if any sources were NULL, clear the respective list
3882         if (!vertexstring)
3883                 vertstrings_count = 0;
3884         if (!geometrystring)
3885                 geomstrings_count = 0;
3886         if (!fragmentstring)
3887                 fragstrings_count = 0;
3888
3889         vertstring_length = 0;
3890         for (i = 0;i < vertstrings_count;i++)
3891                 vertstring_length += strlen(vertstrings_list[i]);
3892         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3893         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3894                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3895
3896         geomstring_length = 0;
3897         for (i = 0;i < geomstrings_count;i++)
3898                 geomstring_length += strlen(geomstrings_list[i]);
3899         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3900         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3901                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3902
3903         fragstring_length = 0;
3904         for (i = 0;i < fragstrings_count;i++)
3905                 fragstring_length += strlen(fragstrings_list[i]);
3906         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3907         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3908                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3909
3910         CHECKGLERROR
3911         CHECKCGERROR
3912         //vertexProfile = CG_PROFILE_ARBVP1;
3913         //fragmentProfile = CG_PROFILE_ARBFP1;
3914         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3915         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3916         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3917         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3918         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3919         CHECKGLERROR
3920
3921         // compile the vertex program
3922         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL)))
3923         {
3924                 CHECKCGERROR
3925 #if 0
3926                 cgCompileProgram(p->vprogram);CHECKCGERROR
3927                 if (!cgIsProgramCompiled(p->vprogram))
3928                 {
3929                         CHECKCGERROR
3930                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3931                         p->vprogram = 0;
3932                 }
3933                 else
3934 #endif
3935                 {
3936                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3937                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3938                         // look up all the uniform variable names we care about, so we don't
3939                         // have to look them up every time we set them
3940                         CHECKCGERROR
3941                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3942                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3943                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3944                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3945                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3946                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3947                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3948                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3949                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3950                         CHECKCGERROR
3951                 }
3952         }
3953
3954         // compile the fragment program
3955         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL)))
3956         {
3957 #if 0
3958                 cgCompileProgram(p->fprogram);CHECKCGERROR
3959                 if (!cgIsProgramCompiled(p->fprogram))
3960                 {
3961                         CHECKCGERROR
3962                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3963                         p->fprogram = 0;
3964                 }
3965                 else
3966 #endif
3967                 {
3968                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3969                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3970                         CHECKCGERROR
3971                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3972                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3973                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3974                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3975                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3976                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3977                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3978                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3979                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3980                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3981                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3982                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3983                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3984                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3985                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3986                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3987                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3988                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3989                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3990                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3991                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3992                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3993                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3994                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3995                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3996                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3997                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3998                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3999                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4000                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4001                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4002                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4003                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4004                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4005                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4006                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4007                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4008                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4009                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4010                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4011                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4012                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4013                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4014                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4015                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4016                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4017                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4018                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4019                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4020                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4021                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4022                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4023                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4024                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4025                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4026                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4027                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4028                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4029                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4030                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4031                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4032                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4033                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4034                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4035                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4036                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4037                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4038                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4039                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4040                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4041                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4042                         p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4043                         CHECKCGERROR
4044                 }
4045         }
4046
4047         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4048                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4049         else
4050                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4051
4052         // free the strings
4053         if (vertstring)
4054                 Mem_Free(vertstring);
4055         if (geomstring)
4056                 Mem_Free(geomstring);
4057         if (fragstring)
4058                 Mem_Free(fragstring);
4059         if (vertexstring)
4060                 Mem_Free(vertexstring);
4061         if (geometrystring)
4062                 Mem_Free(geometrystring);
4063         if (fragmentstring)
4064                 Mem_Free(fragmentstring);
4065 }
4066
4067 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4068 {
4069         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4070         CHECKGLERROR
4071         CHECKCGERROR
4072         if (r_cg_permutation != perm)
4073         {
4074                 r_cg_permutation = perm;
4075                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4076                 {
4077                         if (!r_cg_permutation->compiled)
4078                                 R_CG_CompilePermutation(perm, mode, permutation);
4079                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4080                         {
4081                                 // remove features until we find a valid permutation
4082                                 int i;
4083                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4084                                 {
4085                                         // reduce i more quickly whenever it would not remove any bits
4086                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4087                                         if (!(permutation & j))
4088                                                 continue;
4089                                         permutation -= j;
4090                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4091                                         if (!r_cg_permutation->compiled)
4092                                                 R_CG_CompilePermutation(perm, mode, permutation);
4093                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4094                                                 break;
4095                                 }
4096                                 if (i >= SHADERPERMUTATION_COUNT)
4097                                 {
4098                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4099                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4100                                         return; // no bit left to clear, entire mode is broken
4101                                 }
4102                         }
4103                 }
4104                 CHECKGLERROR
4105                 CHECKCGERROR
4106                 if (r_cg_permutation->vprogram)
4107                 {
4108                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4109                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4110                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4111                 }
4112                 else
4113                 {
4114                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4115                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4116                 }
4117                 if (r_cg_permutation->fprogram)
4118                 {
4119                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4120                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4121                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4122                 }
4123                 else
4124                 {
4125                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4126                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4127                 }
4128         }
4129         CHECKCGERROR
4130         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4131         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4132 }
4133
4134 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4135 {
4136         cgGLSetTextureParameter(param, R_GetTexture(tex));
4137         cgGLEnableTextureParameter(param);
4138 }
4139 #endif
4140
4141 void R_GLSL_Restart_f(void)
4142 {
4143         unsigned int i, limit;
4144         switch(vid.renderpath)
4145         {
4146         case RENDERPATH_GL20:
4147                 {
4148                         r_glsl_permutation_t *p;
4149                         r_glsl_permutation = NULL;
4150                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4151                         for (i = 0;i < limit;i++)
4152                         {
4153                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4154                                 {
4155                                         GL_Backend_FreeProgram(p->program);
4156                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4157                                 }
4158                         }
4159                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4160                 }
4161                 break;
4162         case RENDERPATH_CGGL:
4163 #ifdef SUPPORTCG
4164                 {
4165                         r_cg_permutation_t *p;
4166                         r_cg_permutation = NULL;
4167                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4168                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4169                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4170                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4171                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4172                         for (i = 0;i < limit;i++)
4173                         {
4174                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4175                                 {
4176                                         if (p->vprogram)
4177                                                 cgDestroyProgram(p->vprogram);
4178                                         if (p->fprogram)
4179                                                 cgDestroyProgram(p->fprogram);
4180                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4181                                 }
4182                         }
4183                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4184                 }
4185                 break;
4186 #endif
4187         case RENDERPATH_GL13:
4188         case RENDERPATH_GL11:
4189                 break;
4190         }
4191 }
4192
4193 void R_GLSL_DumpShader_f(void)
4194 {
4195         int i;
4196         qfile_t *file;
4197
4198         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4199         if (file)
4200         {
4201                 FS_Print(file, "/* The engine may define the following macros:\n");
4202                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4203                 for (i = 0;i < SHADERMODE_COUNT;i++)
4204                         FS_Print(file, glslshadermodeinfo[i].pretext);
4205                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4206                         FS_Print(file, shaderpermutationinfo[i].pretext);
4207                 FS_Print(file, "*/\n");
4208                 FS_Print(file, builtinshaderstring);
4209                 FS_Close(file);
4210                 Con_Printf("glsl/default.glsl written\n");
4211         }
4212         else
4213                 Con_Printf("failed to write to glsl/default.glsl\n");
4214
4215 #ifdef SUPPORTCG
4216         file = FS_OpenRealFile("cg/default.cg", "w", false);
4217         if (file)
4218         {
4219                 FS_Print(file, "/* The engine may define the following macros:\n");
4220                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4221                 for (i = 0;i < SHADERMODE_COUNT;i++)
4222                         FS_Print(file, cgshadermodeinfo[i].pretext);
4223                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4224                         FS_Print(file, shaderpermutationinfo[i].pretext);
4225                 FS_Print(file, "*/\n");
4226                 FS_Print(file, builtincgshaderstring);
4227                 FS_Close(file);
4228                 Con_Printf("cg/default.cg written\n");
4229         }
4230         else
4231                 Con_Printf("failed to write to cg/default.cg\n");
4232 #endif
4233 }
4234
4235 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4236 {
4237         if (!second)
4238                 texturemode = GL_MODULATE;
4239         switch (vid.renderpath)
4240         {
4241         case RENDERPATH_GL20:
4242                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4243                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4244                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4245                 break;
4246         case RENDERPATH_CGGL:
4247 #ifdef SUPPORTCG
4248                 CHECKCGERROR
4249                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4250                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4251                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4252 #endif
4253                 break;
4254         case RENDERPATH_GL13:
4255                 R_Mesh_TexBind(0, first );
4256                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4257                 R_Mesh_TexBind(1, second);
4258                 if (second)
4259                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4260                 break;
4261         case RENDERPATH_GL11:
4262                 R_Mesh_TexBind(0, first );
4263                 break;
4264         }
4265 }
4266
4267 void R_SetupShader_DepthOrShadow(void)
4268 {
4269         switch (vid.renderpath)
4270         {
4271         case RENDERPATH_GL20:
4272                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4273                 break;
4274         case RENDERPATH_CGGL:
4275 #ifdef SUPPORTCG
4276                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4277 #endif
4278                 break;
4279         case RENDERPATH_GL13:
4280                 R_Mesh_TexBind(0, 0);
4281                 R_Mesh_TexBind(1, 0);
4282                 break;
4283         case RENDERPATH_GL11:
4284                 R_Mesh_TexBind(0, 0);
4285                 break;
4286         }
4287 }
4288
4289 void R_SetupShader_ShowDepth(void)
4290 {
4291         switch (vid.renderpath)
4292         {
4293         case RENDERPATH_GL20:
4294                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4295                 break;
4296         case RENDERPATH_CGGL:
4297 #ifdef SUPPORTCG
4298                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4299 #endif
4300                 break;
4301         case RENDERPATH_GL13:
4302                 break;
4303         case RENDERPATH_GL11:
4304                 break;
4305         }
4306 }
4307
4308 extern qboolean r_shadow_usingdeferredprepass;
4309 extern cvar_t r_shadow_deferred_8bitrange;
4310 extern rtexture_t *r_shadow_attenuationgradienttexture;
4311 extern rtexture_t *r_shadow_attenuation2dtexture;
4312 extern rtexture_t *r_shadow_attenuation3dtexture;
4313 extern qboolean r_shadow_usingshadowmaprect;
4314 extern qboolean r_shadow_usingshadowmapcube;
4315 extern qboolean r_shadow_usingshadowmap2d;
4316 extern float r_shadow_shadowmap_texturescale[2];
4317 extern float r_shadow_shadowmap_parameters[4];
4318 extern qboolean r_shadow_shadowmapvsdct;
4319 extern qboolean r_shadow_shadowmapsampler;
4320 extern int r_shadow_shadowmappcf;
4321 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4322 extern rtexture_t *r_shadow_shadowmap2dtexture;
4323 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4324 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4325 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4326 extern int r_shadow_prepass_width;
4327 extern int r_shadow_prepass_height;
4328 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4329 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4330 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4331 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4332 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4333 {
4334         // select a permutation of the lighting shader appropriate to this
4335         // combination of texture, entity, light source, and fogging, only use the
4336         // minimum features necessary to avoid wasting rendering time in the
4337         // fragment shader on features that are not being used
4338         unsigned int permutation = 0;
4339         unsigned int mode = 0;
4340         float m16f[16];
4341         if (rsurfacepass == RSURFPASS_BACKGROUND)
4342         {
4343                 // distorted background
4344                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4345                         mode = SHADERMODE_WATER;
4346                 else
4347                         mode = SHADERMODE_REFRACTION;
4348                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4349                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4350                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4351                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4352                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4353                 R_Mesh_ColorPointer(NULL, 0, 0);
4354                 GL_AlphaTest(false);
4355                 GL_BlendFunc(GL_ONE, GL_ZERO);
4356         }
4357         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4358         {
4359                 if (r_glsl_offsetmapping.integer)
4360                 {
4361                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4362                         if (r_glsl_offsetmapping_reliefmapping.integer)
4363                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4364                 }
4365                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4366                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4367                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4368                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4369                 // normalmap (deferred prepass), may use alpha test on diffuse
4370                 mode = SHADERMODE_DEFERREDGEOMETRY;
4371                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4372                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4373                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4374                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4375                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4376                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4377                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4378                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4379                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4380                 else
4381                         R_Mesh_ColorPointer(NULL, 0, 0);
4382                 GL_AlphaTest(false);
4383                 GL_BlendFunc(GL_ONE, GL_ZERO);
4384         }
4385         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4386         {
4387                 if (r_glsl_offsetmapping.integer)
4388                 {
4389                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4390                         if (r_glsl_offsetmapping_reliefmapping.integer)
4391                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4392                 }
4393                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4394                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4395                 // light source
4396                 mode = SHADERMODE_LIGHTSOURCE;
4397                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4398                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4399                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4400                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4401                 if (diffusescale > 0)
4402                         permutation |= SHADERPERMUTATION_DIFFUSE;
4403                 if (specularscale > 0)
4404                 {
4405                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4406                         if (r_shadow_glossexact.integer)
4407                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4408                 }
4409                 if (r_refdef.fogenabled)
4410                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4411                 if (rsurface.texture->colormapping)
4412                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4413                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4414                 {
4415                         if (r_shadow_usingshadowmaprect)
4416                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4417                         if (r_shadow_usingshadowmap2d)
4418                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4419                         if (r_shadow_usingshadowmapcube)
4420                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4421                         else if(r_shadow_shadowmapvsdct)
4422                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4423
4424                         if (r_shadow_shadowmapsampler)
4425                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4426                         if (r_shadow_shadowmappcf > 1)
4427                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4428                         else if (r_shadow_shadowmappcf)
4429                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4430                 }
4431                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4432                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4433                 {
4434                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4435                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4436                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4437                 }
4438                 else
4439                 {
4440                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4441                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4442                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4443                 }
4444                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4445                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4446                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4447                 else
4448                         R_Mesh_ColorPointer(NULL, 0, 0);
4449                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4450                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4451         }
4452         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4453         {
4454                 if (r_glsl_offsetmapping.integer)
4455                 {
4456                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4457                         if (r_glsl_offsetmapping_reliefmapping.integer)
4458                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4459                 }
4460                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4461                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4462                 // unshaded geometry (fullbright or ambient model lighting)
4463                 mode = SHADERMODE_FLATCOLOR;
4464                 ambientscale = diffusescale = specularscale = 0;
4465                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4466                         permutation |= SHADERPERMUTATION_GLOW;
4467                 if (r_refdef.fogenabled)
4468                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4469                 if (rsurface.texture->colormapping)
4470                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4471                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4472                         permutation |= SHADERPERMUTATION_REFLECTION;
4473                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4474                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4475                 {
4476                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4477                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4478                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4479                 }
4480                 else
4481                 {
4482                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4483                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4484                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4485                 }
4486                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4487                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4488                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4489                 else
4490                         R_Mesh_ColorPointer(NULL, 0, 0);
4491                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4492                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4493         }
4494         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4495         {
4496                 if (r_glsl_offsetmapping.integer)
4497                 {
4498                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4499                         if (r_glsl_offsetmapping_reliefmapping.integer)
4500                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4501                 }
4502                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4503                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4504                 // directional model lighting
4505                 mode = SHADERMODE_LIGHTDIRECTION;
4506                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4507                         permutation |= SHADERPERMUTATION_GLOW;
4508                 permutation |= SHADERPERMUTATION_DIFFUSE;
4509                 if (specularscale > 0)
4510                 {
4511                         permutation |= SHADERPERMUTATION_SPECULAR;
4512                         if (r_shadow_glossexact.integer)
4513                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4514                 }
4515                 if (r_refdef.fogenabled)
4516                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4517                 if (rsurface.texture->colormapping)
4518                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4519                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4520                         permutation |= SHADERPERMUTATION_REFLECTION;
4521                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4522                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4523                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4524                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4525                 {
4526                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4527                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4528                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4529                 }
4530                 else
4531                 {
4532                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4533                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4534                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4535                 }
4536                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4537                 R_Mesh_ColorPointer(NULL, 0, 0);
4538                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4539                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4540         }
4541         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4542         {
4543                 if (r_glsl_offsetmapping.integer)
4544                 {
4545                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4546                         if (r_glsl_offsetmapping_reliefmapping.integer)
4547                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4548                 }
4549                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4550                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4551                 // ambient model lighting
4552                 mode = SHADERMODE_LIGHTDIRECTION;
4553                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4554                         permutation |= SHADERPERMUTATION_GLOW;
4555                 if (r_refdef.fogenabled)
4556                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4557                 if (rsurface.texture->colormapping)
4558                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4559                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4560                         permutation |= SHADERPERMUTATION_REFLECTION;
4561                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4562                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4563                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4564                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4565                 {
4566                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4567                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4568                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4569                 }
4570                 else
4571                 {
4572                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4573                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4574                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4575                 }
4576                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4577                 R_Mesh_ColorPointer(NULL, 0, 0);
4578                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4579                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4580         }
4581         else
4582         {
4583                 if (r_glsl_offsetmapping.integer)
4584                 {
4585                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4586                         if (r_glsl_offsetmapping_reliefmapping.integer)
4587                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4588                 }
4589                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4590                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4591                 // lightmapped wall
4592                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4593                         permutation |= SHADERPERMUTATION_GLOW;
4594                 if (r_refdef.fogenabled)
4595                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4596                 if (rsurface.texture->colormapping)
4597                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4598                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4599                         permutation |= SHADERPERMUTATION_REFLECTION;
4600                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4601                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4602                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4603                 {
4604                         // deluxemapping (light direction texture)
4605                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4606                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4607                         else
4608                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4609                         permutation |= SHADERPERMUTATION_DIFFUSE;
4610                         if (specularscale > 0)
4611                         {
4612                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4613                                 if (r_shadow_glossexact.integer)
4614                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4615                         }
4616                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4617                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4618                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4619                         else
4620                                 R_Mesh_ColorPointer(NULL, 0, 0);
4621                 }
4622                 else if (r_glsl_deluxemapping.integer >= 2)
4623                 {
4624                         // fake deluxemapping (uniform light direction in tangentspace)
4625                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4626                         permutation |= SHADERPERMUTATION_DIFFUSE;
4627                         if (specularscale > 0)
4628                         {
4629                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4630                                 if (r_shadow_glossexact.integer)
4631                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4632                         }
4633                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4634                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4635                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4636                         else
4637                                 R_Mesh_ColorPointer(NULL, 0, 0);
4638                 }
4639                 else if (rsurface.uselightmaptexture)
4640                 {
4641                         // ordinary lightmapping (q1bsp, q3bsp)
4642                         mode = SHADERMODE_LIGHTMAP;
4643                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4644                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4645                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4646                         else
4647                                 R_Mesh_ColorPointer(NULL, 0, 0);
4648                 }
4649                 else
4650                 {
4651                         // ordinary vertex coloring (q3bsp)
4652                         mode = SHADERMODE_VERTEXCOLOR;
4653                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4654                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4655                 }
4656                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4657                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4658                 {
4659                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4660                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4661                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4662                 }
4663                 else
4664                 {
4665                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4666                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4667                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4668                 }
4669                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4670                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4671         }
4672         switch(vid.renderpath)
4673         {
4674         case RENDERPATH_GL20:
4675                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4676                 if (mode == SHADERMODE_LIGHTSOURCE)
4677                 {
4678                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4679                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4680                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4681                         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);
4682                         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);
4683                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
4684         
4685                         // additive passes are only darkened by fog, not tinted
4686                         if (r_glsl_permutation->loc_FogColor >= 0)
4687                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4688                         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]);
4689                         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]);
4690                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4691                 }
4692                 else
4693                 {
4694                         if (mode == SHADERMODE_FLATCOLOR)
4695                         {
4696                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4697                         }
4698                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4699                         {
4700                                 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]);
4701                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
4702                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4703                                 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);
4704                                 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);
4705                                 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]);
4706                                 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]);
4707                         }
4708                         else
4709                         {
4710                                 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]);
4711                                 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]);
4712                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4713                                 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);
4714                                 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);
4715                         }
4716                         // additive passes are only darkened by fog, not tinted
4717                         if (r_glsl_permutation->loc_FogColor >= 0)
4718                         {
4719                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4720                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4721                                 else
4722                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4723                         }
4724                         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);
4725                         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]);
4726                         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]);
4727                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4728                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4729                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4730                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4731                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4732                 }
4733                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4734                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4735                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4736                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4737                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4738                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4739                 {
4740                         if (rsurface.texture->pantstexture)
4741                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4742                         else
4743                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4744                 }
4745                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4746                 {
4747                         if (rsurface.texture->shirttexture)
4748                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4749                         else
4750                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4751                 }
4752                 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]);
4753                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4754                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4755                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4756                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4757                 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]);
4758                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4759
4760         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4761         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4762         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4763                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4764                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4765                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4766                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4767                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4768                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4769                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4770                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4771                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4772                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4773                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4774                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4775                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4776                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4777                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4778                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4779                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4780                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4781                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4782                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4783                 if (rsurface.rtlight)
4784                 {
4785                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4786                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4787                         if (r_shadow_usingshadowmapcube)
4788                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4789                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4790                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4791                 }
4792                 CHECKGLERROR
4793                 break;
4794         case RENDERPATH_CGGL:
4795 #ifdef SUPPORTCG
4796                 R_SetupShader_SetPermutationCG(mode, permutation);
4797                 if (mode == SHADERMODE_LIGHTSOURCE)
4798                 {
4799                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4800                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4801                 }
4802                 else
4803                 {
4804                         if (mode == SHADERMODE_LIGHTDIRECTION)
4805                         {
4806                                 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
4807                         }
4808                 }
4809                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4810                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4811                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4812                 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
4813                 CHECKGLERROR
4814
4815                 if (mode == SHADERMODE_LIGHTSOURCE)
4816                 {
4817                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4818                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4819                         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
4820                         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
4821                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
4822
4823                         // additive passes are only darkened by fog, not tinted
4824                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4825                         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
4826                         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
4827                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4828                 }
4829                 else
4830                 {
4831                         if (mode == SHADERMODE_FLATCOLOR)
4832                         {
4833                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4834                         }
4835                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4836                         {
4837                                 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
4838                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
4839                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
4840                                 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
4841                                 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
4842                                 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
4843                                 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
4844                         }
4845                         else
4846                         {
4847                                 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
4848                                 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
4849                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
4850                                 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
4851                                 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
4852                         }
4853                         // additive passes are only darkened by fog, not tinted
4854                         if (r_cg_permutation->fp_FogColor)
4855                         {
4856                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4857                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4858                                 else
4859                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4860                                 CHECKCGERROR
4861                         }
4862                         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
4863                         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
4864                         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
4865                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4866                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4867                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4868                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4869                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4870                 }
4871                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4872                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4873                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4874                 if (r_cg_permutation->fp_Color_Pants)
4875                 {
4876                         if (rsurface.texture->pantstexture)
4877                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4878                         else
4879                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4880                         CHECKCGERROR
4881                 }
4882                 if (r_cg_permutation->fp_Color_Shirt)
4883                 {
4884                         if (rsurface.texture->shirttexture)
4885                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4886                         else
4887                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4888                         CHECKCGERROR
4889                 }
4890                 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
4891                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4892                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4893                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4894                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4895                 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
4896                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
4897
4898         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
4899         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
4900         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
4901                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
4902                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
4903                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
4904                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
4905                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
4906                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
4907                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
4908                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
4909                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
4910                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
4911                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
4912                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
4913                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
4914                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4915                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
4916                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
4917                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4918                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4919                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
4920                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
4921                 if (rsurface.rtlight)
4922                 {
4923                         if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4924                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4925                         if (r_shadow_usingshadowmapcube)
4926                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4927                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4928                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4929                 }
4930
4931                 CHECKGLERROR
4932 #endif
4933                 break;
4934         case RENDERPATH_GL13:
4935         case RENDERPATH_GL11:
4936                 break;
4937         }
4938 }
4939
4940 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4941 {
4942         // select a permutation of the lighting shader appropriate to this
4943         // combination of texture, entity, light source, and fogging, only use the
4944         // minimum features necessary to avoid wasting rendering time in the
4945         // fragment shader on features that are not being used
4946         unsigned int permutation = 0;
4947         unsigned int mode = 0;
4948         const float *lightcolorbase = rtlight->currentcolor;
4949         float ambientscale = rtlight->ambientscale;
4950         float diffusescale = rtlight->diffusescale;
4951         float specularscale = rtlight->specularscale;
4952         // this is the location of the light in view space
4953         vec3_t viewlightorigin;
4954         // this transforms from view space (camera) to light space (cubemap)
4955         matrix4x4_t viewtolight;
4956         matrix4x4_t lighttoview;
4957         float viewtolight16f[16];
4958         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4959         // light source
4960         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4961         if (rtlight->currentcubemap != r_texture_whitecube)
4962                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4963         if (diffusescale > 0)
4964                 permutation |= SHADERPERMUTATION_DIFFUSE;
4965         if (specularscale > 0)
4966         {
4967                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4968                 if (r_shadow_glossexact.integer)
4969                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4970         }
4971         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4972         {
4973                 if (r_shadow_usingshadowmaprect)
4974                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4975                 if (r_shadow_usingshadowmap2d)
4976                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4977                 if (r_shadow_usingshadowmapcube)
4978                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4979                 else if(r_shadow_shadowmapvsdct)
4980                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4981
4982                 if (r_shadow_shadowmapsampler)
4983                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4984                 if (r_shadow_shadowmappcf > 1)
4985                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4986                 else if (r_shadow_shadowmappcf)
4987                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4988         }
4989         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4990         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4991         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4992         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4993         switch(vid.renderpath)
4994         {
4995         case RENDERPATH_GL20:
4996                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4997                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4998                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4999                 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);
5000                 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);
5001                 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);
5002                 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]);
5003                 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]);
5004                 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));
5005                 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]);
5006                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5007
5008                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5009                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5010                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5011                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5012                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5013                 if (r_shadow_usingshadowmapcube)
5014                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5015                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5016                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5017                 break;
5018         case RENDERPATH_CGGL:
5019 #ifdef SUPPORTCG
5020                 R_SetupShader_SetPermutationCG(mode, permutation);
5021                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5022                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5023                 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
5024                 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
5025                 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
5026                 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
5027                 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
5028                 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
5029                 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
5030                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5031
5032                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5033                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5034                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5035                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5036                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5037                 if (r_shadow_usingshadowmapcube)
5038                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5039                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5040                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5041 #endif
5042                 break;
5043         case RENDERPATH_GL13:
5044         case RENDERPATH_GL11:
5045                 break;
5046         }
5047 }
5048
5049 #define SKINFRAME_HASH 1024
5050
5051 typedef struct
5052 {
5053         int loadsequence; // incremented each level change
5054         memexpandablearray_t array;
5055         skinframe_t *hash[SKINFRAME_HASH];
5056 }
5057 r_skinframe_t;
5058 r_skinframe_t r_skinframe;
5059
5060 void R_SkinFrame_PrepareForPurge(void)
5061 {
5062         r_skinframe.loadsequence++;
5063         // wrap it without hitting zero
5064         if (r_skinframe.loadsequence >= 200)
5065                 r_skinframe.loadsequence = 1;
5066 }
5067
5068 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5069 {
5070         if (!skinframe)
5071                 return;
5072         // mark the skinframe as used for the purging code
5073         skinframe->loadsequence = r_skinframe.loadsequence;
5074 }
5075
5076 void R_SkinFrame_Purge(void)
5077 {
5078         int i;
5079         skinframe_t *s;
5080         for (i = 0;i < SKINFRAME_HASH;i++)
5081         {
5082                 for (s = r_skinframe.hash[i];s;s = s->next)
5083                 {
5084                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5085                         {
5086                                 if (s->merged == s->base)
5087                                         s->merged = NULL;
5088                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5089                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5090                                 R_PurgeTexture(s->merged);s->merged = NULL;
5091                                 R_PurgeTexture(s->base  );s->base   = NULL;
5092                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5093                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5094                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5095                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5096                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5097                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5098                                 s->loadsequence = 0;
5099                         }
5100                 }
5101         }
5102 }
5103
5104 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5105         skinframe_t *item;
5106         char basename[MAX_QPATH];
5107
5108         Image_StripImageExtension(name, basename, sizeof(basename));
5109
5110         if( last == NULL ) {
5111                 int hashindex;
5112                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5113                 item = r_skinframe.hash[hashindex];
5114         } else {
5115                 item = last->next;
5116         }
5117
5118         // linearly search through the hash bucket
5119         for( ; item ; item = item->next ) {
5120                 if( !strcmp( item->basename, basename ) ) {
5121                         return item;
5122                 }
5123         }
5124         return NULL;
5125 }
5126
5127 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5128 {
5129         skinframe_t *item;
5130         int hashindex;
5131         char basename[MAX_QPATH];
5132
5133         Image_StripImageExtension(name, basename, sizeof(basename));
5134
5135         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5136         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5137                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5138                         break;
5139
5140         if (!item) {
5141                 rtexture_t *dyntexture;
5142                 // check whether its a dynamic texture
5143                 dyntexture = CL_GetDynTexture( basename );
5144                 if (!add && !dyntexture)
5145                         return NULL;
5146                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5147                 memset(item, 0, sizeof(*item));
5148                 strlcpy(item->basename, basename, sizeof(item->basename));
5149                 item->base = dyntexture; // either NULL or dyntexture handle
5150                 item->textureflags = textureflags;
5151                 item->comparewidth = comparewidth;
5152                 item->compareheight = compareheight;
5153                 item->comparecrc = comparecrc;
5154                 item->next = r_skinframe.hash[hashindex];
5155                 r_skinframe.hash[hashindex] = item;
5156         }
5157         else if( item->base == NULL )
5158         {
5159                 rtexture_t *dyntexture;
5160                 // check whether its a dynamic texture
5161                 // 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]
5162                 dyntexture = CL_GetDynTexture( basename );
5163                 item->base = dyntexture; // either NULL or dyntexture handle
5164         }
5165
5166         R_SkinFrame_MarkUsed(item);
5167         return item;
5168 }
5169
5170 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5171         { \
5172                 unsigned long long avgcolor[5], wsum; \
5173                 int pix, comp, w; \
5174                 avgcolor[0] = 0; \
5175                 avgcolor[1] = 0; \
5176                 avgcolor[2] = 0; \
5177                 avgcolor[3] = 0; \
5178                 avgcolor[4] = 0; \
5179                 wsum = 0; \
5180                 for(pix = 0; pix < cnt; ++pix) \
5181                 { \
5182                         w = 0; \
5183                         for(comp = 0; comp < 3; ++comp) \
5184                                 w += getpixel; \
5185                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5186                         { \
5187                                 ++wsum; \
5188                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5189                                 w = getpixel; \
5190                                 for(comp = 0; comp < 3; ++comp) \
5191                                         avgcolor[comp] += getpixel * w; \
5192                                 avgcolor[3] += w; \
5193                         } \
5194                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5195                         avgcolor[4] += getpixel; \
5196                 } \
5197                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5198                         avgcolor[3] = 1; \
5199                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5200                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5201                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5202                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5203         }
5204
5205 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5206 {
5207         int j;
5208         unsigned char *pixels;
5209         unsigned char *bumppixels;
5210         unsigned char *basepixels = NULL;
5211         int basepixels_width = 0;
5212         int basepixels_height = 0;
5213         skinframe_t *skinframe;
5214         rtexture_t *ddsbase = NULL;
5215         qboolean ddshasalpha = false;
5216         float ddsavgcolor[4];
5217         char basename[MAX_QPATH];
5218
5219         if (cls.state == ca_dedicated)
5220                 return NULL;
5221
5222         // return an existing skinframe if already loaded
5223         // if loading of the first image fails, don't make a new skinframe as it
5224         // would cause all future lookups of this to be missing
5225         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5226         if (skinframe && skinframe->base)
5227                 return skinframe;
5228
5229         Image_StripImageExtension(name, basename, sizeof(basename));
5230
5231         // check for DDS texture file first
5232         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5233         {
5234                 basepixels = loadimagepixelsbgra(name, complain, true);
5235                 if (basepixels == NULL)
5236                         return NULL;
5237         }
5238
5239         if (developer_loading.integer)
5240                 Con_Printf("loading skin \"%s\"\n", name);
5241
5242         // we've got some pixels to store, so really allocate this new texture now
5243         if (!skinframe)
5244                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5245         skinframe->stain = NULL;
5246         skinframe->merged = NULL;
5247         skinframe->base = NULL;
5248         skinframe->pants = NULL;
5249         skinframe->shirt = NULL;
5250         skinframe->nmap = NULL;
5251         skinframe->gloss = NULL;
5252         skinframe->glow = NULL;
5253         skinframe->fog = NULL;
5254         skinframe->hasalpha = false;
5255
5256         if (ddsbase)
5257         {
5258                 skinframe->base = ddsbase;
5259                 skinframe->hasalpha = ddshasalpha;
5260                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5261                 if (r_loadfog && skinframe->hasalpha)
5262                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5263                 //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]);
5264         }
5265         else
5266         {
5267                 basepixels_width = image_width;
5268                 basepixels_height = image_height;
5269                 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);
5270                 if (textureflags & TEXF_ALPHA)
5271                 {
5272                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5273                         {
5274                                 if (basepixels[j] < 255)
5275                                 {
5276                                         skinframe->hasalpha = true;
5277                                         break;
5278                                 }
5279                         }
5280                         if (r_loadfog && skinframe->hasalpha)
5281                         {
5282                                 // has transparent pixels
5283                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5284                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5285                                 {
5286                                         pixels[j+0] = 255;
5287                                         pixels[j+1] = 255;
5288                                         pixels[j+2] = 255;
5289                                         pixels[j+3] = basepixels[j+3];
5290                                 }
5291                                 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);
5292                                 Mem_Free(pixels);
5293                         }
5294                 }
5295                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5296                 //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]);
5297                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5298                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5299                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5300                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5301         }
5302
5303         if (r_loaddds)
5304         {
5305                 if (r_loadnormalmap)
5306                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5307                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5308                 if (r_loadgloss)
5309                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5310                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5311                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5312         }
5313
5314         // _norm is the name used by tenebrae and has been adopted as standard
5315         if (r_loadnormalmap && skinframe->nmap == NULL)
5316         {
5317                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5318                 {
5319                         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);
5320                         Mem_Free(pixels);
5321                         pixels = NULL;
5322                 }
5323                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5324                 {
5325                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5326                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5327                         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);
5328                         Mem_Free(pixels);
5329                         Mem_Free(bumppixels);
5330                 }
5331                 else if (r_shadow_bumpscale_basetexture.value > 0)
5332                 {
5333                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5334                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5335                         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);
5336                         Mem_Free(pixels);
5337                 }
5338                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5339                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5340         }
5341
5342         // _luma is supported only for tenebrae compatibility
5343         // _glow is the preferred name
5344         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5345         {
5346                 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);
5347                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5348                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5349                 Mem_Free(pixels);pixels = NULL;
5350         }
5351
5352         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5353         {
5354                 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);
5355                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5356                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5357                 Mem_Free(pixels);
5358                 pixels = NULL;
5359         }
5360
5361         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5362         {
5363                 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);
5364                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5365                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5366                 Mem_Free(pixels);
5367                 pixels = NULL;
5368         }
5369
5370         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5371         {
5372                 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);
5373                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5374                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5375                 Mem_Free(pixels);
5376                 pixels = NULL;
5377         }
5378
5379         if (basepixels)
5380                 Mem_Free(basepixels);
5381
5382         return skinframe;
5383 }
5384
5385 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5386 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5387 {
5388         int i;
5389         unsigned char *temp1, *temp2;
5390         skinframe_t *skinframe;
5391
5392         if (cls.state == ca_dedicated)
5393                 return NULL;
5394
5395         // if already loaded just return it, otherwise make a new skinframe
5396         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5397         if (skinframe && skinframe->base)
5398                 return skinframe;
5399
5400         skinframe->stain = NULL;
5401         skinframe->merged = NULL;
5402         skinframe->base = NULL;
5403         skinframe->pants = NULL;
5404         skinframe->shirt = NULL;
5405         skinframe->nmap = NULL;
5406         skinframe->gloss = NULL;
5407         skinframe->glow = NULL;
5408         skinframe->fog = NULL;
5409         skinframe->hasalpha = false;
5410
5411         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5412         if (!skindata)
5413                 return NULL;
5414
5415         if (developer_loading.integer)
5416                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5417
5418         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5419         {
5420                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5421                 temp2 = temp1 + width * height * 4;
5422                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5423                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5424                 Mem_Free(temp1);
5425         }
5426         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5427         if (textureflags & TEXF_ALPHA)
5428         {
5429                 for (i = 3;i < width * height * 4;i += 4)
5430                 {
5431                         if (skindata[i] < 255)
5432                         {
5433                                 skinframe->hasalpha = true;
5434                                 break;
5435                         }
5436                 }
5437                 if (r_loadfog && skinframe->hasalpha)
5438                 {
5439                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5440                         memcpy(fogpixels, skindata, width * height * 4);
5441                         for (i = 0;i < width * height * 4;i += 4)
5442                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5443                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5444                         Mem_Free(fogpixels);
5445                 }
5446         }
5447
5448         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5449         //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]);
5450
5451         return skinframe;
5452 }
5453
5454 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5455 {
5456         int i;
5457         int featuresmask;
5458         skinframe_t *skinframe;
5459
5460         if (cls.state == ca_dedicated)
5461                 return NULL;
5462
5463         // if already loaded just return it, otherwise make a new skinframe
5464         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5465         if (skinframe && skinframe->base)
5466                 return skinframe;
5467
5468         skinframe->stain = NULL;
5469         skinframe->merged = NULL;
5470         skinframe->base = NULL;
5471         skinframe->pants = NULL;
5472         skinframe->shirt = NULL;
5473         skinframe->nmap = NULL;
5474         skinframe->gloss = NULL;
5475         skinframe->glow = NULL;
5476         skinframe->fog = NULL;
5477         skinframe->hasalpha = false;
5478
5479         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5480         if (!skindata)
5481                 return NULL;
5482
5483         if (developer_loading.integer)
5484                 Con_Printf("loading quake skin \"%s\"\n", name);
5485
5486         // 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)
5487         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5488         memcpy(skinframe->qpixels, skindata, width*height);
5489         skinframe->qwidth = width;
5490         skinframe->qheight = height;
5491
5492         featuresmask = 0;
5493         for (i = 0;i < width * height;i++)
5494                 featuresmask |= palette_featureflags[skindata[i]];
5495
5496         skinframe->hasalpha = false;
5497         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5498         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5499         skinframe->qgeneratemerged = true;
5500         skinframe->qgeneratebase = skinframe->qhascolormapping;
5501         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5502
5503         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5504         //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]);
5505
5506         return skinframe;
5507 }
5508
5509 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5510 {
5511         int width;
5512         int height;
5513         unsigned char *skindata;
5514
5515         if (!skinframe->qpixels)
5516                 return;
5517
5518         if (!skinframe->qhascolormapping)
5519                 colormapped = false;
5520
5521         if (colormapped)
5522         {
5523                 if (!skinframe->qgeneratebase)
5524                         return;
5525         }
5526         else
5527         {
5528                 if (!skinframe->qgeneratemerged)
5529                         return;
5530         }
5531
5532         width = skinframe->qwidth;
5533         height = skinframe->qheight;
5534         skindata = skinframe->qpixels;
5535
5536         if (skinframe->qgeneratenmap)
5537         {
5538                 unsigned char *temp1, *temp2;
5539                 skinframe->qgeneratenmap = false;
5540                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5541                 temp2 = temp1 + width * height * 4;
5542                 // use either a custom palette or the quake palette
5543                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5544                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5545                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5546                 Mem_Free(temp1);
5547         }
5548
5549         if (skinframe->qgenerateglow)
5550         {
5551                 skinframe->qgenerateglow = false;
5552                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5553         }
5554
5555         if (colormapped)
5556         {
5557                 skinframe->qgeneratebase = false;
5558                 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);
5559                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5560                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5561         }
5562         else
5563         {
5564                 skinframe->qgeneratemerged = false;
5565                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5566         }
5567
5568         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5569         {
5570                 Mem_Free(skinframe->qpixels);
5571                 skinframe->qpixels = NULL;
5572         }
5573 }
5574
5575 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)
5576 {
5577         int i;
5578         skinframe_t *skinframe;
5579
5580         if (cls.state == ca_dedicated)
5581                 return NULL;
5582
5583         // if already loaded just return it, otherwise make a new skinframe
5584         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5585         if (skinframe && skinframe->base)
5586                 return skinframe;
5587
5588         skinframe->stain = NULL;
5589         skinframe->merged = NULL;
5590         skinframe->base = NULL;
5591         skinframe->pants = NULL;
5592         skinframe->shirt = NULL;
5593         skinframe->nmap = NULL;
5594         skinframe->gloss = NULL;
5595         skinframe->glow = NULL;
5596         skinframe->fog = NULL;
5597         skinframe->hasalpha = false;
5598
5599         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5600         if (!skindata)
5601                 return NULL;
5602
5603         if (developer_loading.integer)
5604                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5605
5606         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5607         if (textureflags & TEXF_ALPHA)
5608         {
5609                 for (i = 0;i < width * height;i++)
5610                 {
5611                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5612                         {
5613                                 skinframe->hasalpha = true;
5614                                 break;
5615                         }
5616                 }
5617                 if (r_loadfog && skinframe->hasalpha)
5618                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5619         }
5620
5621         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5622         //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]);
5623
5624         return skinframe;
5625 }
5626
5627 skinframe_t *R_SkinFrame_LoadMissing(void)
5628 {
5629         skinframe_t *skinframe;
5630
5631         if (cls.state == ca_dedicated)
5632                 return NULL;
5633
5634         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5635         skinframe->stain = NULL;
5636         skinframe->merged = NULL;
5637         skinframe->base = NULL;
5638         skinframe->pants = NULL;
5639         skinframe->shirt = NULL;
5640         skinframe->nmap = NULL;
5641         skinframe->gloss = NULL;
5642         skinframe->glow = NULL;
5643         skinframe->fog = NULL;
5644         skinframe->hasalpha = false;
5645
5646         skinframe->avgcolor[0] = rand() / RAND_MAX;
5647         skinframe->avgcolor[1] = rand() / RAND_MAX;
5648         skinframe->avgcolor[2] = rand() / RAND_MAX;
5649         skinframe->avgcolor[3] = 1;
5650
5651         return skinframe;
5652 }
5653
5654 void R_Main_FreeViewCache(void)
5655 {
5656         if (r_refdef.viewcache.entityvisible)
5657                 Mem_Free(r_refdef.viewcache.entityvisible);
5658         if (r_refdef.viewcache.world_pvsbits)
5659                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5660         if (r_refdef.viewcache.world_leafvisible)
5661                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5662         if (r_refdef.viewcache.world_surfacevisible)
5663                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5664         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5665 }
5666
5667 void R_Main_ResizeViewCache(void)
5668 {
5669         int numentities = r_refdef.scene.numentities;
5670         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5671         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5672         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5673         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5674         if (r_refdef.viewcache.maxentities < numentities)
5675         {
5676                 r_refdef.viewcache.maxentities = numentities;
5677                 if (r_refdef.viewcache.entityvisible)
5678                         Mem_Free(r_refdef.viewcache.entityvisible);
5679                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5680         }
5681         if (r_refdef.viewcache.world_numclusters != numclusters)
5682         {
5683                 r_refdef.viewcache.world_numclusters = numclusters;
5684                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5685                 if (r_refdef.viewcache.world_pvsbits)
5686                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5687                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5688         }
5689         if (r_refdef.viewcache.world_numleafs != numleafs)
5690         {
5691                 r_refdef.viewcache.world_numleafs = numleafs;
5692                 if (r_refdef.viewcache.world_leafvisible)
5693                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5694                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5695         }
5696         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5697         {
5698                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5699                 if (r_refdef.viewcache.world_surfacevisible)
5700                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5701                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5702         }
5703 }
5704
5705 extern rtexture_t *loadingscreentexture;
5706 void gl_main_start(void)
5707 {
5708         loadingscreentexture = NULL;
5709         r_texture_blanknormalmap = NULL;
5710         r_texture_white = NULL;
5711         r_texture_grey128 = NULL;
5712         r_texture_black = NULL;
5713         r_texture_whitecube = NULL;
5714         r_texture_normalizationcube = NULL;
5715         r_texture_fogattenuation = NULL;
5716         r_texture_gammaramps = NULL;
5717
5718         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5719         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5720
5721         switch(vid.renderpath)
5722         {
5723         case RENDERPATH_GL20:
5724         case RENDERPATH_CGGL:
5725                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5726                 Cvar_SetValueQuick(&gl_combine, 1);
5727                 Cvar_SetValueQuick(&r_glsl, 1);
5728                 r_loadnormalmap = true;
5729                 r_loadgloss = true;
5730                 r_loadfog = false;
5731                 break;
5732         case RENDERPATH_GL13:
5733                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5734                 Cvar_SetValueQuick(&gl_combine, 1);
5735                 Cvar_SetValueQuick(&r_glsl, 0);
5736                 r_loadnormalmap = false;
5737                 r_loadgloss = false;
5738                 r_loadfog = true;
5739                 break;
5740         case RENDERPATH_GL11:
5741                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5742                 Cvar_SetValueQuick(&gl_combine, 0);
5743                 Cvar_SetValueQuick(&r_glsl, 0);
5744                 r_loadnormalmap = false;
5745                 r_loadgloss = false;
5746                 r_loadfog = true;
5747                 break;
5748         }
5749
5750         R_AnimCache_Free();
5751         R_FrameData_Reset();
5752
5753         r_numqueries = 0;
5754         r_maxqueries = 0;
5755         memset(r_queries, 0, sizeof(r_queries));
5756
5757         r_qwskincache = NULL;
5758         r_qwskincache_size = 0;
5759
5760         // set up r_skinframe loading system for textures
5761         memset(&r_skinframe, 0, sizeof(r_skinframe));
5762         r_skinframe.loadsequence = 1;
5763         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5764
5765         r_main_texturepool = R_AllocTexturePool();
5766         R_BuildBlankTextures();
5767         R_BuildNoTexture();
5768         if (vid.support.arb_texture_cube_map)
5769         {
5770                 R_BuildWhiteCube();
5771                 R_BuildNormalizationCube();
5772         }
5773         r_texture_fogattenuation = NULL;
5774         r_texture_gammaramps = NULL;
5775         //r_texture_fogintensity = NULL;
5776         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5777         memset(&r_waterstate, 0, sizeof(r_waterstate));
5778         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5779         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5780 #ifdef SUPPORTCG
5781         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5782         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5783 #endif
5784         memset(&r_svbsp, 0, sizeof (r_svbsp));
5785
5786         r_refdef.fogmasktable_density = 0;
5787 }
5788
5789 void gl_main_shutdown(void)
5790 {
5791         R_AnimCache_Free();
5792         R_FrameData_Reset();
5793
5794         R_Main_FreeViewCache();
5795
5796         if (r_maxqueries)
5797                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5798
5799         r_numqueries = 0;
5800         r_maxqueries = 0;
5801         memset(r_queries, 0, sizeof(r_queries));
5802
5803         r_qwskincache = NULL;
5804         r_qwskincache_size = 0;
5805
5806         // clear out the r_skinframe state
5807         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5808         memset(&r_skinframe, 0, sizeof(r_skinframe));
5809
5810         if (r_svbsp.nodes)
5811                 Mem_Free(r_svbsp.nodes);
5812         memset(&r_svbsp, 0, sizeof (r_svbsp));
5813         R_FreeTexturePool(&r_main_texturepool);
5814         loadingscreentexture = NULL;
5815         r_texture_blanknormalmap = NULL;
5816         r_texture_white = NULL;
5817         r_texture_grey128 = NULL;
5818         r_texture_black = NULL;
5819         r_texture_whitecube = NULL;
5820         r_texture_normalizationcube = NULL;
5821         r_texture_fogattenuation = NULL;
5822         r_texture_gammaramps = NULL;
5823         //r_texture_fogintensity = NULL;
5824         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5825         memset(&r_waterstate, 0, sizeof(r_waterstate));
5826         R_GLSL_Restart_f();
5827 }
5828
5829 extern void CL_ParseEntityLump(char *entitystring);
5830 void gl_main_newmap(void)
5831 {
5832         // FIXME: move this code to client
5833         int l;
5834         char *entities, entname[MAX_QPATH];
5835         if (r_qwskincache)
5836                 Mem_Free(r_qwskincache);
5837         r_qwskincache = NULL;
5838         r_qwskincache_size = 0;
5839         if (cl.worldmodel)
5840         {
5841                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5842                 l = (int)strlen(entname) - 4;
5843                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5844                 {
5845                         memcpy(entname + l, ".ent", 5);
5846                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5847                         {
5848                                 CL_ParseEntityLump(entities);
5849                                 Mem_Free(entities);
5850                                 return;
5851                         }
5852                 }
5853                 if (cl.worldmodel->brush.entities)
5854                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5855         }
5856         R_Main_FreeViewCache();
5857
5858         R_FrameData_Reset();
5859 }
5860
5861 void GL_Main_Init(void)
5862 {
5863         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5864
5865         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5866         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5867         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5868         if (gamemode == GAME_NEHAHRA)
5869         {
5870                 Cvar_RegisterVariable (&gl_fogenable);
5871                 Cvar_RegisterVariable (&gl_fogdensity);
5872                 Cvar_RegisterVariable (&gl_fogred);
5873                 Cvar_RegisterVariable (&gl_foggreen);
5874                 Cvar_RegisterVariable (&gl_fogblue);
5875                 Cvar_RegisterVariable (&gl_fogstart);
5876                 Cvar_RegisterVariable (&gl_fogend);
5877                 Cvar_RegisterVariable (&gl_skyclip);
5878         }
5879         Cvar_RegisterVariable(&r_motionblur);
5880         Cvar_RegisterVariable(&r_motionblur_maxblur);
5881         Cvar_RegisterVariable(&r_motionblur_bmin);
5882         Cvar_RegisterVariable(&r_motionblur_vmin);
5883         Cvar_RegisterVariable(&r_motionblur_vmax);
5884         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5885         Cvar_RegisterVariable(&r_motionblur_randomize);
5886         Cvar_RegisterVariable(&r_damageblur);
5887         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5888         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5889         Cvar_RegisterVariable(&r_equalize_entities_by);
5890         Cvar_RegisterVariable(&r_equalize_entities_to);
5891         Cvar_RegisterVariable(&r_depthfirst);
5892         Cvar_RegisterVariable(&r_useinfinitefarclip);
5893         Cvar_RegisterVariable(&r_farclip_base);
5894         Cvar_RegisterVariable(&r_farclip_world);
5895         Cvar_RegisterVariable(&r_nearclip);
5896         Cvar_RegisterVariable(&r_showbboxes);
5897         Cvar_RegisterVariable(&r_showsurfaces);
5898         Cvar_RegisterVariable(&r_showtris);
5899         Cvar_RegisterVariable(&r_shownormals);
5900         Cvar_RegisterVariable(&r_showlighting);
5901         Cvar_RegisterVariable(&r_showshadowvolumes);
5902         Cvar_RegisterVariable(&r_showcollisionbrushes);
5903         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5904         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5905         Cvar_RegisterVariable(&r_showdisabledepthtest);
5906         Cvar_RegisterVariable(&r_drawportals);
5907         Cvar_RegisterVariable(&r_drawentities);
5908         Cvar_RegisterVariable(&r_cullentities_trace);
5909         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5910         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5911         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5912         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5913         Cvar_RegisterVariable(&r_drawviewmodel);
5914         Cvar_RegisterVariable(&r_speeds);
5915         Cvar_RegisterVariable(&r_fullbrights);
5916         Cvar_RegisterVariable(&r_wateralpha);
5917         Cvar_RegisterVariable(&r_dynamic);
5918         Cvar_RegisterVariable(&r_fullbright);
5919         Cvar_RegisterVariable(&r_shadows);
5920         Cvar_RegisterVariable(&r_shadows_darken);
5921         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5922         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5923         Cvar_RegisterVariable(&r_shadows_throwdistance);
5924         Cvar_RegisterVariable(&r_shadows_throwdirection);
5925         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5926         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5927         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5928         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5929         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5930         Cvar_RegisterVariable(&r_fog_exp2);
5931         Cvar_RegisterVariable(&r_drawfog);
5932         Cvar_RegisterVariable(&r_transparentdepthmasking);
5933         Cvar_RegisterVariable(&r_texture_dds_load);
5934         Cvar_RegisterVariable(&r_texture_dds_save);
5935         Cvar_RegisterVariable(&r_textureunits);
5936         Cvar_RegisterVariable(&gl_combine);
5937         Cvar_RegisterVariable(&r_glsl);
5938         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5939         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5940         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5941         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5942         Cvar_RegisterVariable(&r_glsl_postprocess);
5943         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5944         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5945         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5946         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5947         Cvar_RegisterVariable(&r_water);
5948         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5949         Cvar_RegisterVariable(&r_water_clippingplanebias);
5950         Cvar_RegisterVariable(&r_water_refractdistort);
5951         Cvar_RegisterVariable(&r_water_reflectdistort);
5952         Cvar_RegisterVariable(&r_lerpsprites);
5953         Cvar_RegisterVariable(&r_lerpmodels);
5954         Cvar_RegisterVariable(&r_lerplightstyles);
5955         Cvar_RegisterVariable(&r_waterscroll);
5956         Cvar_RegisterVariable(&r_bloom);
5957         Cvar_RegisterVariable(&r_bloom_colorscale);
5958         Cvar_RegisterVariable(&r_bloom_brighten);
5959         Cvar_RegisterVariable(&r_bloom_blur);
5960         Cvar_RegisterVariable(&r_bloom_resolution);
5961         Cvar_RegisterVariable(&r_bloom_colorexponent);
5962         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5963         Cvar_RegisterVariable(&r_hdr);
5964         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5965         Cvar_RegisterVariable(&r_hdr_glowintensity);
5966         Cvar_RegisterVariable(&r_hdr_range);
5967         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5968         Cvar_RegisterVariable(&developer_texturelogging);
5969         Cvar_RegisterVariable(&gl_lightmaps);
5970         Cvar_RegisterVariable(&r_test);
5971         Cvar_RegisterVariable(&r_batchmode);
5972         Cvar_RegisterVariable(&r_glsl_saturation);
5973         Cvar_RegisterVariable(&r_framedatasize);
5974         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5975                 Cvar_SetValue("r_fullbrights", 0);
5976         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5977
5978         Cvar_RegisterVariable(&r_track_sprites);
5979         Cvar_RegisterVariable(&r_track_sprites_flags);
5980         Cvar_RegisterVariable(&r_track_sprites_scalew);
5981         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5982         Cvar_RegisterVariable(&r_overheadsprites_perspective);
5983         Cvar_RegisterVariable(&r_overheadsprites_pushback);
5984 }
5985
5986 extern void R_Textures_Init(void);
5987 extern void GL_Draw_Init(void);
5988 extern void GL_Main_Init(void);
5989 extern void R_Shadow_Init(void);
5990 extern void R_Sky_Init(void);
5991 extern void GL_Surf_Init(void);
5992 extern void R_Particles_Init(void);
5993 extern void R_Explosion_Init(void);
5994 extern void gl_backend_init(void);
5995 extern void Sbar_Init(void);
5996 extern void R_LightningBeams_Init(void);
5997 extern void Mod_RenderInit(void);
5998 extern void Font_Init(void);
5999
6000 void Render_Init(void)
6001 {
6002         gl_backend_init();
6003         R_Textures_Init();
6004         GL_Main_Init();
6005         Font_Init();
6006         GL_Draw_Init();
6007         R_Shadow_Init();
6008         R_Sky_Init();
6009         GL_Surf_Init();
6010         Sbar_Init();
6011         R_Particles_Init();
6012         R_Explosion_Init();
6013         R_LightningBeams_Init();
6014         Mod_RenderInit();
6015 }
6016
6017 /*
6018 ===============
6019 GL_Init
6020 ===============
6021 */
6022 extern char *ENGINE_EXTENSIONS;
6023 void GL_Init (void)
6024 {
6025         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6026         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6027         gl_version = (const char *)qglGetString(GL_VERSION);
6028         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6029
6030         if (!gl_extensions)
6031                 gl_extensions = "";
6032         if (!gl_platformextensions)
6033                 gl_platformextensions = "";
6034
6035         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6036         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6037         Con_Printf("GL_VERSION: %s\n", gl_version);
6038         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6039         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6040
6041         VID_CheckExtensions();
6042
6043         // LordHavoc: report supported extensions
6044         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6045
6046         // clear to black (loading plaque will be seen over this)
6047         CHECKGLERROR
6048         qglClearColor(0,0,0,1);CHECKGLERROR
6049         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6050 }
6051
6052 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6053 {
6054         int i;
6055         mplane_t *p;
6056         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6057         {
6058                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6059                 if (i == 4)
6060                         continue;
6061                 p = r_refdef.view.frustum + i;
6062                 switch(p->signbits)
6063                 {
6064                 default:
6065                 case 0:
6066                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6067                                 return true;
6068                         break;
6069                 case 1:
6070                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6071                                 return true;
6072                         break;
6073                 case 2:
6074                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6075                                 return true;
6076                         break;
6077                 case 3:
6078                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6079                                 return true;
6080                         break;
6081                 case 4:
6082                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6083                                 return true;
6084                         break;
6085                 case 5:
6086                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6087                                 return true;
6088                         break;
6089                 case 6:
6090                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6091                                 return true;
6092                         break;
6093                 case 7:
6094                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6095                                 return true;
6096                         break;
6097                 }
6098         }
6099         return false;
6100 }
6101
6102 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6103 {
6104         int i;
6105         const mplane_t *p;
6106         for (i = 0;i < numplanes;i++)
6107         {
6108                 p = planes + i;
6109                 switch(p->signbits)
6110                 {
6111                 default:
6112                 case 0:
6113                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6114                                 return true;
6115                         break;
6116                 case 1:
6117                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6118                                 return true;
6119                         break;
6120                 case 2:
6121                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6122                                 return true;
6123                         break;
6124                 case 3:
6125                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6126                                 return true;
6127                         break;
6128                 case 4:
6129                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6130                                 return true;
6131                         break;
6132                 case 5:
6133                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6134                                 return true;
6135                         break;
6136                 case 6:
6137                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6138                                 return true;
6139                         break;
6140                 case 7:
6141                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6142                                 return true;
6143                         break;
6144                 }
6145         }
6146         return false;
6147 }
6148
6149 //==================================================================================
6150
6151 // LordHavoc: this stores temporary data used within the same frame
6152
6153 qboolean r_framedata_failed;
6154 static size_t r_framedata_size;
6155 static size_t r_framedata_current;
6156 static void *r_framedata_base;
6157
6158 void R_FrameData_Reset(void)
6159 {
6160         if (r_framedata_base)
6161                 Mem_Free(r_framedata_base);
6162         r_framedata_base = NULL;
6163         r_framedata_size = 0;
6164         r_framedata_current = 0;
6165         r_framedata_failed = false;
6166 }
6167
6168 void R_FrameData_NewFrame(void)
6169 {
6170         size_t wantedsize;
6171         if (r_framedata_failed)
6172                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6173         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6174         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6175         if (r_framedata_size != wantedsize)
6176         {
6177                 r_framedata_size = wantedsize;
6178                 if (r_framedata_base)
6179                         Mem_Free(r_framedata_base);
6180                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6181         }
6182         r_framedata_current = 0;
6183         r_framedata_failed = false;
6184 }
6185
6186 void *R_FrameData_Alloc(size_t size)
6187 {
6188         void *data;
6189
6190         // align to 16 byte boundary
6191         size = (size + 15) & ~15;
6192         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6193         r_framedata_current += size;
6194
6195         // check overflow
6196         if (r_framedata_current > r_framedata_size)
6197                 r_framedata_failed = true;
6198
6199         // return NULL on everything after a failure
6200         if (r_framedata_failed)
6201                 return NULL;
6202
6203         return data;
6204 }
6205
6206 void *R_FrameData_Store(size_t size, void *data)
6207 {
6208         void *d = R_FrameData_Alloc(size);
6209         if (d)
6210                 memcpy(d, data, size);
6211         return d;
6212 }
6213
6214 //==================================================================================
6215
6216 // LordHavoc: animcache originally written by Echon, rewritten since then
6217
6218 /**
6219  * Animation cache prevents re-generating mesh data for an animated model
6220  * multiple times in one frame for lighting, shadowing, reflections, etc.
6221  */
6222
6223 void R_AnimCache_Free(void)
6224 {
6225 }
6226
6227 void R_AnimCache_ClearCache(void)
6228 {
6229         int i;
6230         entity_render_t *ent;
6231
6232         for (i = 0;i < r_refdef.scene.numentities;i++)
6233         {
6234                 ent = r_refdef.scene.entities[i];
6235                 ent->animcache_vertex3f = NULL;
6236                 ent->animcache_normal3f = NULL;
6237                 ent->animcache_svector3f = NULL;
6238                 ent->animcache_tvector3f = NULL;
6239         }
6240 }
6241
6242 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6243 {
6244         dp_model_t *model = ent->model;
6245         int numvertices;
6246         // see if it's already cached this frame
6247         if (ent->animcache_vertex3f)
6248         {
6249                 // add normals/tangents if needed
6250                 if (wantnormals || wanttangents)
6251                 {
6252                         if (ent->animcache_normal3f)
6253                                 wantnormals = false;
6254                         if (ent->animcache_svector3f)
6255                                 wanttangents = false;
6256                         if (wantnormals || wanttangents)
6257                         {
6258                                 numvertices = model->surfmesh.num_vertices;
6259                                 if (wantnormals)
6260                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6261                                 if (wanttangents)
6262                                 {
6263                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6264                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6265                                 }
6266                                 if (!r_framedata_failed)
6267                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6268                         }
6269                 }
6270         }
6271         else
6272         {
6273                 // see if this ent is worth caching
6274                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6275                         return false;
6276                 // get some memory for this entity and generate mesh data
6277                 numvertices = model->surfmesh.num_vertices;
6278                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6279                 if (wantnormals)
6280                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6281                 if (wanttangents)
6282                 {
6283                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6284                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6285                 }
6286                 if (!r_framedata_failed)
6287                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6288         }
6289         return !r_framedata_failed;
6290 }
6291
6292 void R_AnimCache_CacheVisibleEntities(void)
6293 {
6294         int i;
6295         qboolean wantnormals = !r_showsurfaces.integer;
6296         qboolean wanttangents = !r_showsurfaces.integer;
6297
6298         switch(vid.renderpath)
6299         {
6300         case RENDERPATH_GL20:
6301         case RENDERPATH_CGGL:
6302                 break;
6303         case RENDERPATH_GL13:
6304         case RENDERPATH_GL11:
6305                 wanttangents = false;
6306                 break;
6307         }
6308
6309         // TODO: thread this
6310         // NOTE: R_PrepareRTLights() also caches entities
6311
6312         for (i = 0;i < r_refdef.scene.numentities;i++)
6313                 if (r_refdef.viewcache.entityvisible[i])
6314                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6315
6316         if (r_shadows.integer)
6317                 for (i = 0;i < r_refdef.scene.numentities;i++)
6318                         if (!r_refdef.viewcache.entityvisible[i])
6319                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6320 }
6321
6322 //==================================================================================
6323
6324 static void R_View_UpdateEntityLighting (void)
6325 {
6326         int i;
6327         entity_render_t *ent;
6328         vec3_t tempdiffusenormal, avg;
6329         vec_t f, fa, fd, fdd;
6330
6331         for (i = 0;i < r_refdef.scene.numentities;i++)
6332         {
6333                 ent = r_refdef.scene.entities[i];
6334
6335                 // skip unseen models
6336                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6337                         continue;
6338
6339                 // skip bsp models
6340                 if (ent->model && ent->model->brush.num_leafs)
6341                 {
6342                         // TODO: use modellight for r_ambient settings on world?
6343                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6344                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6345                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6346                         continue;
6347                 }
6348
6349                 // fetch the lighting from the worldmodel data
6350                 VectorClear(ent->modellight_ambient);
6351                 VectorClear(ent->modellight_diffuse);
6352                 VectorClear(tempdiffusenormal);
6353                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6354                 {
6355                         vec3_t org;
6356                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6357                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6358                         if(ent->flags & RENDER_EQUALIZE)
6359                         {
6360                                 // first fix up ambient lighting...
6361                                 if(r_equalize_entities_minambient.value > 0)
6362                                 {
6363                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6364                                         if(fd > 0)
6365                                         {
6366                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6367                                                 if(fa < r_equalize_entities_minambient.value * fd)
6368                                                 {
6369                                                         // solve:
6370                                                         //   fa'/fd' = minambient
6371                                                         //   fa'+0.25*fd' = fa+0.25*fd
6372                                                         //   ...
6373                                                         //   fa' = fd' * minambient
6374                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6375                                                         //   ...
6376                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6377                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6378                                                         //   ...
6379                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6380                                                         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
6381                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6382                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6383                                                 }
6384                                         }
6385                                 }
6386
6387                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6388                                 {
6389                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6390                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6391                                         if(f > 0)
6392                                         {
6393                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6394                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6395                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6396                                         }
6397                                 }
6398                         }
6399                 }
6400                 else // highly rare
6401                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6402
6403                 // move the light direction into modelspace coordinates for lighting code
6404                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6405                 if(VectorLength2(ent->modellight_lightdir) == 0)
6406                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6407                 VectorNormalize(ent->modellight_lightdir);
6408         }
6409 }
6410
6411 #define MAX_LINEOFSIGHTTRACES 64
6412
6413 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6414 {
6415         int i;
6416         vec3_t boxmins, boxmaxs;
6417         vec3_t start;
6418         vec3_t end;
6419         dp_model_t *model = r_refdef.scene.worldmodel;
6420
6421         if (!model || !model->brush.TraceLineOfSight)
6422                 return true;
6423
6424         // expand the box a little
6425         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6426         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6427         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6428         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6429         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6430         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6431
6432         // try center
6433         VectorCopy(eye, start);
6434         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6435         if (model->brush.TraceLineOfSight(model, start, end))
6436                 return true;
6437
6438         // try various random positions
6439         for (i = 0;i < numsamples;i++)
6440         {
6441                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6442                 if (model->brush.TraceLineOfSight(model, start, end))
6443                         return true;
6444         }
6445
6446         return false;
6447 }
6448
6449
6450 static void R_View_UpdateEntityVisible (void)
6451 {
6452         int i;
6453         int renderimask;
6454         int samples;
6455         entity_render_t *ent;
6456
6457         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6458         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6459         {
6460                 // worldmodel can check visibility
6461                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6462                 for (i = 0;i < r_refdef.scene.numentities;i++)
6463                 {
6464                         ent = r_refdef.scene.entities[i];
6465                         if (!(ent->flags & renderimask))
6466                         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)))
6467                         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))
6468                                 r_refdef.viewcache.entityvisible[i] = true;
6469                 }
6470                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6471                 {
6472                         for (i = 0;i < r_refdef.scene.numentities;i++)
6473                         {
6474                                 ent = r_refdef.scene.entities[i];
6475                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6476                                 {
6477                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6478                                         if (samples < 0)
6479                                                 continue; // temp entities do pvs only
6480                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6481                                                 ent->last_trace_visibility = realtime;
6482                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6483                                                 r_refdef.viewcache.entityvisible[i] = 0;
6484                                 }
6485                         }
6486                 }
6487         }
6488         else
6489         {
6490                 // no worldmodel or it can't check visibility
6491                 for (i = 0;i < r_refdef.scene.numentities;i++)
6492                 {
6493                         ent = r_refdef.scene.entities[i];
6494                         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));
6495                 }
6496         }
6497 }
6498
6499 /// only used if skyrendermasked, and normally returns false
6500 int R_DrawBrushModelsSky (void)
6501 {
6502         int i, sky;
6503         entity_render_t *ent;
6504
6505         sky = false;
6506         for (i = 0;i < r_refdef.scene.numentities;i++)
6507         {
6508                 if (!r_refdef.viewcache.entityvisible[i])
6509                         continue;
6510                 ent = r_refdef.scene.entities[i];
6511                 if (!ent->model || !ent->model->DrawSky)
6512                         continue;
6513                 ent->model->DrawSky(ent);
6514                 sky = true;
6515         }
6516         return sky;
6517 }
6518
6519 static void R_DrawNoModel(entity_render_t *ent);
6520 static void R_DrawModels(void)
6521 {
6522         int i;
6523         entity_render_t *ent;
6524
6525         for (i = 0;i < r_refdef.scene.numentities;i++)
6526         {
6527                 if (!r_refdef.viewcache.entityvisible[i])
6528                         continue;
6529                 ent = r_refdef.scene.entities[i];
6530                 r_refdef.stats.entities++;
6531                 if (ent->model && ent->model->Draw != NULL)
6532                         ent->model->Draw(ent);
6533                 else
6534                         R_DrawNoModel(ent);
6535         }
6536 }
6537
6538 static void R_DrawModelsDepth(void)
6539 {
6540         int i;
6541         entity_render_t *ent;
6542
6543         for (i = 0;i < r_refdef.scene.numentities;i++)
6544         {
6545                 if (!r_refdef.viewcache.entityvisible[i])
6546                         continue;
6547                 ent = r_refdef.scene.entities[i];
6548                 if (ent->model && ent->model->DrawDepth != NULL)
6549                         ent->model->DrawDepth(ent);
6550         }
6551 }
6552
6553 static void R_DrawModelsDebug(void)
6554 {
6555         int i;
6556         entity_render_t *ent;
6557
6558         for (i = 0;i < r_refdef.scene.numentities;i++)
6559         {
6560                 if (!r_refdef.viewcache.entityvisible[i])
6561                         continue;
6562                 ent = r_refdef.scene.entities[i];
6563                 if (ent->model && ent->model->DrawDebug != NULL)
6564                         ent->model->DrawDebug(ent);
6565         }
6566 }
6567
6568 static void R_DrawModelsAddWaterPlanes(void)
6569 {
6570         int i;
6571         entity_render_t *ent;
6572
6573         for (i = 0;i < r_refdef.scene.numentities;i++)
6574         {
6575                 if (!r_refdef.viewcache.entityvisible[i])
6576                         continue;
6577                 ent = r_refdef.scene.entities[i];
6578                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6579                         ent->model->DrawAddWaterPlanes(ent);
6580         }
6581 }
6582
6583 static void R_View_SetFrustum(void)
6584 {
6585         int i;
6586         double slopex, slopey;
6587         vec3_t forward, left, up, origin;
6588
6589         // we can't trust r_refdef.view.forward and friends in reflected scenes
6590         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6591
6592 #if 0
6593         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6594         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6595         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6596         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6597         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6598         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6599         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6600         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6601         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6602         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6603         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6604         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6605 #endif
6606
6607 #if 0
6608         zNear = r_refdef.nearclip;
6609         nudge = 1.0 - 1.0 / (1<<23);
6610         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6611         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6612         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6613         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6614         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6615         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6616         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6617         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6618 #endif
6619
6620
6621
6622 #if 0
6623         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6624         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6625         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6626         r_refdef.view.frustum[0].dist = m[15] - m[12];
6627
6628         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6629         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6630         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6631         r_refdef.view.frustum[1].dist = m[15] + m[12];
6632
6633         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6634         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6635         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6636         r_refdef.view.frustum[2].dist = m[15] - m[13];
6637
6638         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6639         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6640         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6641         r_refdef.view.frustum[3].dist = m[15] + m[13];
6642
6643         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6644         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6645         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6646         r_refdef.view.frustum[4].dist = m[15] - m[14];
6647
6648         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6649         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6650         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6651         r_refdef.view.frustum[5].dist = m[15] + m[14];
6652 #endif
6653
6654         if (r_refdef.view.useperspective)
6655         {
6656                 slopex = 1.0 / r_refdef.view.frustum_x;
6657                 slopey = 1.0 / r_refdef.view.frustum_y;
6658                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6659                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6660                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6661                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6662                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6663
6664                 // Leaving those out was a mistake, those were in the old code, and they
6665                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6666                 // I couldn't reproduce it after adding those normalizations. --blub
6667                 VectorNormalize(r_refdef.view.frustum[0].normal);
6668                 VectorNormalize(r_refdef.view.frustum[1].normal);
6669                 VectorNormalize(r_refdef.view.frustum[2].normal);
6670                 VectorNormalize(r_refdef.view.frustum[3].normal);
6671
6672                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6673                 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]);
6674                 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]);
6675                 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]);
6676                 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]);
6677
6678                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6679                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6680                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6681                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6682                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6683         }
6684         else
6685         {
6686                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6687                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6688                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6689                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6690                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6691                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6692                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6693                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6694                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6695                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6696         }
6697         r_refdef.view.numfrustumplanes = 5;
6698
6699         if (r_refdef.view.useclipplane)
6700         {
6701                 r_refdef.view.numfrustumplanes = 6;
6702                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6703         }
6704
6705         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6706                 PlaneClassify(r_refdef.view.frustum + i);
6707
6708         // LordHavoc: note to all quake engine coders, Quake had a special case
6709         // for 90 degrees which assumed a square view (wrong), so I removed it,
6710         // Quake2 has it disabled as well.
6711
6712         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6713         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6714         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6715         //PlaneClassify(&frustum[0]);
6716
6717         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6718         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6719         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6720         //PlaneClassify(&frustum[1]);
6721
6722         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6723         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6724         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6725         //PlaneClassify(&frustum[2]);
6726
6727         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6728         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6729         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6730         //PlaneClassify(&frustum[3]);
6731
6732         // nearclip plane
6733         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6734         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6735         //PlaneClassify(&frustum[4]);
6736 }
6737
6738 void R_View_Update(void)
6739 {
6740         R_Main_ResizeViewCache();
6741         R_View_SetFrustum();
6742         R_View_WorldVisibility(r_refdef.view.useclipplane);
6743         R_View_UpdateEntityVisible();
6744         R_View_UpdateEntityLighting();
6745 }
6746
6747 void R_SetupView(qboolean allowwaterclippingplane)
6748 {
6749         const float *customclipplane = NULL;
6750         float plane[4];
6751         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6752         {
6753                 // LordHavoc: couldn't figure out how to make this approach the
6754                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6755                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6756                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6757                         dist = r_refdef.view.clipplane.dist;
6758                 plane[0] = r_refdef.view.clipplane.normal[0];
6759                 plane[1] = r_refdef.view.clipplane.normal[1];
6760                 plane[2] = r_refdef.view.clipplane.normal[2];
6761                 plane[3] = dist;
6762                 customclipplane = plane;
6763         }
6764
6765         if (!r_refdef.view.useperspective)
6766                 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);
6767         else if (vid.stencil && r_useinfinitefarclip.integer)
6768                 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);
6769         else
6770                 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);
6771         R_SetViewport(&r_refdef.view.viewport);
6772 }
6773
6774 void R_EntityMatrix(const matrix4x4_t *matrix)
6775 {
6776         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6777         {
6778                 gl_modelmatrixchanged = false;
6779                 gl_modelmatrix = *matrix;
6780                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6781                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6782                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6783                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6784                 CHECKGLERROR
6785                 switch(vid.renderpath)
6786                 {
6787                 case RENDERPATH_GL20:
6788                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6789                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6790                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6791                         break;
6792                 case RENDERPATH_CGGL:
6793 #ifdef SUPPORTCG
6794                         CHECKCGERROR
6795                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6796                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6797                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6798 #endif
6799                         break;
6800                 case RENDERPATH_GL13:
6801                 case RENDERPATH_GL11:
6802                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6803                         break;
6804                 }
6805         }
6806 }
6807
6808 void R_ResetViewRendering2D(void)
6809 {
6810         r_viewport_t viewport;
6811         DrawQ_Finish();
6812
6813         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6814         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);
6815         R_SetViewport(&viewport);
6816         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6817         GL_Color(1, 1, 1, 1);
6818         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6819         GL_BlendFunc(GL_ONE, GL_ZERO);
6820         GL_AlphaTest(false);
6821         GL_ScissorTest(false);
6822         GL_DepthMask(false);
6823         GL_DepthRange(0, 1);
6824         GL_DepthTest(false);
6825         R_EntityMatrix(&identitymatrix);
6826         R_Mesh_ResetTextureState();
6827         GL_PolygonOffset(0, 0);
6828         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6829         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6830         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6831         qglStencilMask(~0);CHECKGLERROR
6832         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6833         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6834         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6835 }
6836
6837 void R_ResetViewRendering3D(void)
6838 {
6839         DrawQ_Finish();
6840
6841         R_SetupView(true);
6842         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6843         GL_Color(1, 1, 1, 1);
6844         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6845         GL_BlendFunc(GL_ONE, GL_ZERO);
6846         GL_AlphaTest(false);
6847         GL_ScissorTest(true);
6848         GL_DepthMask(true);
6849         GL_DepthRange(0, 1);
6850         GL_DepthTest(true);
6851         R_EntityMatrix(&identitymatrix);
6852         R_Mesh_ResetTextureState();
6853         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6854         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6855         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6856         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6857         qglStencilMask(~0);CHECKGLERROR
6858         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6859         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6860         GL_CullFace(r_refdef.view.cullface_back);
6861 }
6862
6863 void R_RenderScene(void);
6864 void R_RenderWaterPlanes(void);
6865
6866 static void R_Water_StartFrame(void)
6867 {
6868         int i;
6869         int waterwidth, waterheight, texturewidth, textureheight;
6870         r_waterstate_waterplane_t *p;
6871
6872         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6873                 return;
6874
6875         switch(vid.renderpath)
6876         {
6877         case RENDERPATH_GL20:
6878         case RENDERPATH_CGGL:
6879                 break;
6880         case RENDERPATH_GL13:
6881         case RENDERPATH_GL11:
6882                 return;
6883         }
6884
6885         // set waterwidth and waterheight to the water resolution that will be
6886         // used (often less than the screen resolution for faster rendering)
6887         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6888         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6889
6890         // calculate desired texture sizes
6891         // can't use water if the card does not support the texture size
6892         if (!r_water.integer || r_showsurfaces.integer)
6893                 texturewidth = textureheight = waterwidth = waterheight = 0;
6894         else if (vid.support.arb_texture_non_power_of_two)
6895         {
6896                 texturewidth = waterwidth;
6897                 textureheight = waterheight;
6898         }
6899         else
6900         {
6901                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6902                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6903         }
6904
6905         // allocate textures as needed
6906         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6907         {
6908                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6909                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6910                 {
6911                         if (p->texture_refraction)
6912                                 R_FreeTexture(p->texture_refraction);
6913                         p->texture_refraction = NULL;
6914                         if (p->texture_reflection)
6915                                 R_FreeTexture(p->texture_reflection);
6916                         p->texture_reflection = NULL;
6917                 }
6918                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6919                 r_waterstate.texturewidth = texturewidth;
6920                 r_waterstate.textureheight = textureheight;
6921         }
6922
6923         if (r_waterstate.texturewidth)
6924         {
6925                 r_waterstate.enabled = true;
6926
6927                 // when doing a reduced render (HDR) we want to use a smaller area
6928                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6929                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6930
6931                 // set up variables that will be used in shader setup
6932                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6933                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6934                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6935                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6936         }
6937
6938         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6939         r_waterstate.numwaterplanes = 0;
6940 }
6941
6942 void R_Water_AddWaterPlane(msurface_t *surface)
6943 {
6944         int triangleindex, planeindex;
6945         const int *e;
6946         vec3_t vert[3];
6947         vec3_t normal;
6948         vec3_t center;
6949         mplane_t plane;
6950         r_waterstate_waterplane_t *p;
6951         texture_t *t = R_GetCurrentTexture(surface->texture);
6952         // just use the first triangle with a valid normal for any decisions
6953         VectorClear(normal);
6954         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6955         {
6956                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6957                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6958                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6959                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6960                 if (VectorLength2(normal) >= 0.001)
6961                         break;
6962         }
6963
6964         VectorCopy(normal, plane.normal);
6965         VectorNormalize(plane.normal);
6966         plane.dist = DotProduct(vert[0], plane.normal);
6967         PlaneClassify(&plane);
6968         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6969         {
6970                 // skip backfaces (except if nocullface is set)
6971                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6972                         return;
6973                 VectorNegate(plane.normal, plane.normal);
6974                 plane.dist *= -1;
6975                 PlaneClassify(&plane);
6976         }
6977
6978
6979         // find a matching plane if there is one
6980         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6981                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6982                         break;
6983         if (planeindex >= r_waterstate.maxwaterplanes)
6984                 return; // nothing we can do, out of planes
6985
6986         // if this triangle does not fit any known plane rendered this frame, add one
6987         if (planeindex >= r_waterstate.numwaterplanes)
6988         {
6989                 // store the new plane
6990                 r_waterstate.numwaterplanes++;
6991                 p->plane = plane;
6992                 // clear materialflags and pvs
6993                 p->materialflags = 0;
6994                 p->pvsvalid = false;
6995         }
6996         // merge this surface's materialflags into the waterplane
6997         p->materialflags |= t->currentmaterialflags;
6998         // merge this surface's PVS into the waterplane
6999         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7000         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7001          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7002         {
7003                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7004                 p->pvsvalid = true;
7005         }
7006 }
7007
7008 static void R_Water_ProcessPlanes(void)
7009 {
7010         r_refdef_view_t originalview;
7011         r_refdef_view_t myview;
7012         int planeindex;
7013         r_waterstate_waterplane_t *p;
7014
7015         originalview = r_refdef.view;
7016
7017         // make sure enough textures are allocated
7018         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7019         {
7020                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7021                 {
7022                         if (!p->texture_refraction)
7023                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7024                         if (!p->texture_refraction)
7025                                 goto error;
7026                 }
7027
7028                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7029                 {
7030                         if (!p->texture_reflection)
7031                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7032                         if (!p->texture_reflection)
7033                                 goto error;
7034                 }
7035         }
7036
7037         // render views
7038         r_refdef.view = originalview;
7039         r_refdef.view.showdebug = false;
7040         r_refdef.view.width = r_waterstate.waterwidth;
7041         r_refdef.view.height = r_waterstate.waterheight;
7042         r_refdef.view.useclipplane = true;
7043         myview = r_refdef.view;
7044         r_waterstate.renderingscene = true;
7045         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7046         {
7047                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7048                 {
7049                         r_refdef.view = myview;
7050                         // render reflected scene and copy into texture
7051                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7052                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7053                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7054                         r_refdef.view.clipplane = p->plane;
7055                         // reverse the cullface settings for this render
7056                         r_refdef.view.cullface_front = GL_FRONT;
7057                         r_refdef.view.cullface_back = GL_BACK;
7058                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7059                         {
7060                                 r_refdef.view.usecustompvs = true;
7061                                 if (p->pvsvalid)
7062                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7063                                 else
7064                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7065                         }
7066
7067                         R_ResetViewRendering3D();
7068                         R_ClearScreen(r_refdef.fogenabled);
7069                         R_View_Update();
7070                         R_RenderScene();
7071
7072                         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);
7073                 }
7074
7075                 // render the normal view scene and copy into texture
7076                 // (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)
7077                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7078                 {
7079                         r_refdef.view = myview;
7080                         r_refdef.view.clipplane = p->plane;
7081                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7082                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7083                         PlaneClassify(&r_refdef.view.clipplane);
7084
7085                         R_ResetViewRendering3D();
7086                         R_ClearScreen(r_refdef.fogenabled);
7087                         R_View_Update();
7088                         R_RenderScene();
7089
7090                         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);
7091                 }
7092
7093         }
7094         r_waterstate.renderingscene = false;
7095         r_refdef.view = originalview;
7096         R_ResetViewRendering3D();
7097         R_ClearScreen(r_refdef.fogenabled);
7098         R_View_Update();
7099         return;
7100 error:
7101         r_refdef.view = originalview;
7102         r_waterstate.renderingscene = false;
7103         Cvar_SetValueQuick(&r_water, 0);
7104         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7105         return;
7106 }
7107
7108 void R_Bloom_StartFrame(void)
7109 {
7110         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7111
7112         switch(vid.renderpath)
7113         {
7114         case RENDERPATH_GL20:
7115         case RENDERPATH_CGGL:
7116                 break;
7117         case RENDERPATH_GL13:
7118         case RENDERPATH_GL11:
7119                 return;
7120         }
7121
7122         // set bloomwidth and bloomheight to the bloom resolution that will be
7123         // used (often less than the screen resolution for faster rendering)
7124         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7125         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7126         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7127         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7128         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7129
7130         // calculate desired texture sizes
7131         if (vid.support.arb_texture_non_power_of_two)
7132         {
7133                 screentexturewidth = r_refdef.view.width;
7134                 screentextureheight = r_refdef.view.height;
7135                 bloomtexturewidth = r_bloomstate.bloomwidth;
7136                 bloomtextureheight = r_bloomstate.bloomheight;
7137         }
7138         else
7139         {
7140                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7141                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7142                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7143                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7144         }
7145
7146         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))
7147         {
7148                 Cvar_SetValueQuick(&r_hdr, 0);
7149                 Cvar_SetValueQuick(&r_bloom, 0);
7150                 Cvar_SetValueQuick(&r_motionblur, 0);
7151                 Cvar_SetValueQuick(&r_damageblur, 0);
7152         }
7153
7154         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)))
7155                 screentexturewidth = screentextureheight = 0;
7156         if (!r_hdr.integer && !r_bloom.integer)
7157                 bloomtexturewidth = bloomtextureheight = 0;
7158
7159         // allocate textures as needed
7160         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7161         {
7162                 if (r_bloomstate.texture_screen)
7163                         R_FreeTexture(r_bloomstate.texture_screen);
7164                 r_bloomstate.texture_screen = NULL;
7165                 r_bloomstate.screentexturewidth = screentexturewidth;
7166                 r_bloomstate.screentextureheight = screentextureheight;
7167                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7168                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7169         }
7170         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7171         {
7172                 if (r_bloomstate.texture_bloom)
7173                         R_FreeTexture(r_bloomstate.texture_bloom);
7174                 r_bloomstate.texture_bloom = NULL;
7175                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7176                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7177                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7178                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7179         }
7180
7181         // when doing a reduced render (HDR) we want to use a smaller area
7182         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7183         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7184         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7185         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7186         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7187
7188         // set up a texcoord array for the full resolution screen image
7189         // (we have to keep this around to copy back during final render)
7190         r_bloomstate.screentexcoord2f[0] = 0;
7191         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7192         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7193         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7194         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7195         r_bloomstate.screentexcoord2f[5] = 0;
7196         r_bloomstate.screentexcoord2f[6] = 0;
7197         r_bloomstate.screentexcoord2f[7] = 0;
7198
7199         // set up a texcoord array for the reduced resolution bloom image
7200         // (which will be additive blended over the screen image)
7201         r_bloomstate.bloomtexcoord2f[0] = 0;
7202         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7203         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7204         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7205         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7206         r_bloomstate.bloomtexcoord2f[5] = 0;
7207         r_bloomstate.bloomtexcoord2f[6] = 0;
7208         r_bloomstate.bloomtexcoord2f[7] = 0;
7209
7210         if (r_hdr.integer || r_bloom.integer)
7211         {
7212                 r_bloomstate.enabled = true;
7213                 r_bloomstate.hdr = r_hdr.integer != 0;
7214         }
7215
7216         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);
7217 }
7218
7219 void R_Bloom_CopyBloomTexture(float colorscale)
7220 {
7221         r_refdef.stats.bloom++;
7222
7223         // scale down screen texture to the bloom texture size
7224         CHECKGLERROR
7225         R_SetViewport(&r_bloomstate.viewport);
7226         GL_BlendFunc(GL_ONE, GL_ZERO);
7227         GL_Color(colorscale, colorscale, colorscale, 1);
7228         // TODO: optimize with multitexture or GLSL
7229         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7230         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
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         // we now have a bloom image in the framebuffer
7235         // copy it into the bloom image texture for later processing
7236         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);
7237         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7238 }
7239
7240 void R_Bloom_CopyHDRTexture(void)
7241 {
7242         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);
7243         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7244 }
7245
7246 void R_Bloom_MakeTexture(void)
7247 {
7248         int x, range, dir;
7249         float xoffset, yoffset, r, brighten;
7250
7251         r_refdef.stats.bloom++;
7252
7253         R_ResetViewRendering2D();
7254         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7255         R_Mesh_ColorPointer(NULL, 0, 0);
7256
7257         // we have a bloom image in the framebuffer
7258         CHECKGLERROR
7259         R_SetViewport(&r_bloomstate.viewport);
7260
7261         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7262         {
7263                 x *= 2;
7264                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7265                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7266                 GL_Color(r, r, r, 1);
7267                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7268                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7269                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7270                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7271
7272                 // copy the vertically blurred bloom view to a texture
7273                 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);
7274                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7275         }
7276
7277         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7278         brighten = r_bloom_brighten.value;
7279         if (r_hdr.integer)
7280                 brighten *= r_hdr_range.value;
7281         brighten = sqrt(brighten);
7282         if(range >= 1)
7283                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7284         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7285         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7286
7287         for (dir = 0;dir < 2;dir++)
7288         {
7289                 // blend on at multiple vertical offsets to achieve a vertical blur
7290                 // TODO: do offset blends using GLSL
7291                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7292                 GL_BlendFunc(GL_ONE, GL_ZERO);
7293                 for (x = -range;x <= range;x++)
7294                 {
7295                         if (!dir){xoffset = 0;yoffset = x;}
7296                         else {xoffset = x;yoffset = 0;}
7297                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7298                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7299                         // compute a texcoord array with the specified x and y offset
7300                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7301                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7302                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7303                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7304                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7305                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7306                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7307                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7308                         // this r value looks like a 'dot' particle, fading sharply to
7309                         // black at the edges
7310                         // (probably not realistic but looks good enough)
7311                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7312                         //r = brighten/(range*2+1);
7313                         r = brighten / (range * 2 + 1);
7314                         if(range >= 1)
7315                                 r *= (1 - x*x/(float)(range*range));
7316                         GL_Color(r, r, r, 1);
7317                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7318                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7319                         GL_BlendFunc(GL_ONE, GL_ONE);
7320                 }
7321
7322                 // copy the vertically blurred bloom view to a texture
7323                 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);
7324                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7325         }
7326
7327         // apply subtract last
7328         // (just like it would be in a GLSL shader)
7329         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7330         {
7331                 GL_BlendFunc(GL_ONE, GL_ZERO);
7332                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7333                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7334                 GL_Color(1, 1, 1, 1);
7335                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7336                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7337
7338                 GL_BlendFunc(GL_ONE, GL_ONE);
7339                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7340                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7341                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7342                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7343                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7344                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7345                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7346
7347                 // copy the darkened bloom view to a texture
7348                 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);
7349                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7350         }
7351 }
7352
7353 void R_HDR_RenderBloomTexture(void)
7354 {
7355         int oldwidth, oldheight;
7356         float oldcolorscale;
7357
7358         oldcolorscale = r_refdef.view.colorscale;
7359         oldwidth = r_refdef.view.width;
7360         oldheight = r_refdef.view.height;
7361         r_refdef.view.width = r_bloomstate.bloomwidth;
7362         r_refdef.view.height = r_bloomstate.bloomheight;
7363
7364         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7365         // TODO: add exposure compensation features
7366         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7367
7368         r_refdef.view.showdebug = false;
7369         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7370
7371         R_ResetViewRendering3D();
7372
7373         R_ClearScreen(r_refdef.fogenabled);
7374         if (r_timereport_active)
7375                 R_TimeReport("HDRclear");
7376
7377         R_View_Update();
7378         if (r_timereport_active)
7379                 R_TimeReport("visibility");
7380
7381         // only do secondary renders with HDR if r_hdr is 2 or higher
7382         r_waterstate.numwaterplanes = 0;
7383         if (r_waterstate.enabled && r_hdr.integer >= 2)
7384                 R_RenderWaterPlanes();
7385
7386         r_refdef.view.showdebug = true;
7387         R_RenderScene();
7388         r_waterstate.numwaterplanes = 0;
7389
7390         R_ResetViewRendering2D();
7391
7392         R_Bloom_CopyHDRTexture();
7393         R_Bloom_MakeTexture();
7394
7395         // restore the view settings
7396         r_refdef.view.width = oldwidth;
7397         r_refdef.view.height = oldheight;
7398         r_refdef.view.colorscale = oldcolorscale;
7399
7400         R_ResetViewRendering3D();
7401
7402         R_ClearScreen(r_refdef.fogenabled);
7403         if (r_timereport_active)
7404                 R_TimeReport("viewclear");
7405 }
7406
7407 static void R_BlendView(void)
7408 {
7409         unsigned int permutation;
7410         float uservecs[4][4];
7411
7412         switch (vid.renderpath)
7413         {
7414         case RENDERPATH_GL20:
7415         case RENDERPATH_CGGL:
7416                 permutation =
7417                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7418                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7419                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7420                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7421                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7422
7423                 if (r_bloomstate.texture_screen)
7424                 {
7425                         // make sure the buffer is available
7426                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7427
7428                         R_ResetViewRendering2D();
7429                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7430                         R_Mesh_ColorPointer(NULL, 0, 0);
7431
7432                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7433                         {
7434                                 // declare variables
7435                                 float speed;
7436                                 static float avgspeed;
7437
7438                                 speed = VectorLength(cl.movement_velocity);
7439
7440                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7441                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7442
7443                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7444                                 speed = bound(0, speed, 1);
7445                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7446
7447                                 // calculate values into a standard alpha
7448                                 cl.motionbluralpha = 1 - exp(-
7449                                                 (
7450                                                  (r_motionblur.value * speed / 80)
7451                                                  +
7452                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7453                                                 )
7454                                                 /
7455                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7456                                            );
7457
7458                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7459                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7460                                 // apply the blur
7461                                 if (cl.motionbluralpha > 0)
7462                                 {
7463                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7464                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7465                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7466                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7467                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7468                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7469                                 }
7470                         }
7471
7472                         // copy view into the screen texture
7473                         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);
7474                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7475                 }
7476                 else if (!r_bloomstate.texture_bloom)
7477                 {
7478                         // we may still have to do view tint...
7479                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7480                         {
7481                                 // apply a color tint to the whole view
7482                                 R_ResetViewRendering2D();
7483                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7484                                 R_Mesh_ColorPointer(NULL, 0, 0);
7485                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7486                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7487                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7488                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7489                         }
7490                         break; // no screen processing, no bloom, skip it
7491                 }
7492
7493                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7494                 {
7495                         // render simple bloom effect
7496                         // copy the screen and shrink it and darken it for the bloom process
7497                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7498                         // make the bloom texture
7499                         R_Bloom_MakeTexture();
7500                 }
7501
7502 #if _MSC_VER >= 1400
7503 #define sscanf sscanf_s
7504 #endif
7505                 memset(uservecs, 0, sizeof(uservecs));
7506                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7507                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7508                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7509                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7510
7511                 R_ResetViewRendering2D();
7512                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7513                 R_Mesh_ColorPointer(NULL, 0, 0);
7514                 GL_Color(1, 1, 1, 1);
7515                 GL_BlendFunc(GL_ONE, GL_ZERO);
7516                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7517                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7518
7519                 switch(vid.renderpath)
7520                 {
7521                 case RENDERPATH_GL20:
7522                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7523                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7524                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7525                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7526                         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]);
7527                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7528                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7529                         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]);
7530                         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]);
7531                         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]);
7532                         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]);
7533                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7534                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7535                         break;
7536                 case RENDERPATH_CGGL:
7537 #ifdef SUPPORTCG
7538                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7539                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7540                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7541                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7542                         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
7543                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7544                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7545                         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
7546                         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
7547                         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
7548                         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
7549                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7550                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7551 #endif
7552                         break;
7553                 default:
7554                         break;
7555                 }
7556                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7557                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7558                 break;
7559         case RENDERPATH_GL13:
7560         case RENDERPATH_GL11:
7561                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7562                 {
7563                         // apply a color tint to the whole view
7564                         R_ResetViewRendering2D();
7565                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7566                         R_Mesh_ColorPointer(NULL, 0, 0);
7567                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7568                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7569                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7570                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7571                 }
7572                 break;
7573         }
7574 }
7575
7576 matrix4x4_t r_waterscrollmatrix;
7577
7578 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7579 {
7580         if (r_refdef.fog_density)
7581         {
7582                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7583                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7584                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7585
7586                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7587                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7588                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7589                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7590
7591                 {
7592                         vec3_t fogvec;
7593                         VectorCopy(r_refdef.fogcolor, fogvec);
7594                         //   color.rgb *= ContrastBoost * SceneBrightness;
7595                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7596                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7597                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7598                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7599                 }
7600         }
7601 }
7602
7603 void R_UpdateVariables(void)
7604 {
7605         R_Textures_Frame();
7606
7607         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7608
7609         r_refdef.farclip = r_farclip_base.value;
7610         if (r_refdef.scene.worldmodel)
7611                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7612         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7613
7614         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7615                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7616         r_refdef.polygonfactor = 0;
7617         r_refdef.polygonoffset = 0;
7618         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7619         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7620
7621         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7622         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7623         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7624         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7625         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7626         if (r_showsurfaces.integer)
7627         {
7628                 r_refdef.scene.rtworld = false;
7629                 r_refdef.scene.rtworldshadows = false;
7630                 r_refdef.scene.rtdlight = false;
7631                 r_refdef.scene.rtdlightshadows = false;
7632                 r_refdef.lightmapintensity = 0;
7633         }
7634
7635         if (gamemode == GAME_NEHAHRA)
7636         {
7637                 if (gl_fogenable.integer)
7638                 {
7639                         r_refdef.oldgl_fogenable = true;
7640                         r_refdef.fog_density = gl_fogdensity.value;
7641                         r_refdef.fog_red = gl_fogred.value;
7642                         r_refdef.fog_green = gl_foggreen.value;
7643                         r_refdef.fog_blue = gl_fogblue.value;
7644                         r_refdef.fog_alpha = 1;
7645                         r_refdef.fog_start = 0;
7646                         r_refdef.fog_end = gl_skyclip.value;
7647                         r_refdef.fog_height = 1<<30;
7648                         r_refdef.fog_fadedepth = 128;
7649                 }
7650                 else if (r_refdef.oldgl_fogenable)
7651                 {
7652                         r_refdef.oldgl_fogenable = false;
7653                         r_refdef.fog_density = 0;
7654                         r_refdef.fog_red = 0;
7655                         r_refdef.fog_green = 0;
7656                         r_refdef.fog_blue = 0;
7657                         r_refdef.fog_alpha = 0;
7658                         r_refdef.fog_start = 0;
7659                         r_refdef.fog_end = 0;
7660                         r_refdef.fog_height = 1<<30;
7661                         r_refdef.fog_fadedepth = 128;
7662                 }
7663         }
7664
7665         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7666         r_refdef.fog_start = max(0, r_refdef.fog_start);
7667         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7668
7669         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7670
7671         if (r_refdef.fog_density && r_drawfog.integer)
7672         {
7673                 r_refdef.fogenabled = true;
7674                 // this is the point where the fog reaches 0.9986 alpha, which we
7675                 // consider a good enough cutoff point for the texture
7676                 // (0.9986 * 256 == 255.6)
7677                 if (r_fog_exp2.integer)
7678                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7679                 else
7680                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7681                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7682                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7683                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7684                 // fog color was already set
7685                 // update the fog texture
7686                 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)
7687                         R_BuildFogTexture();
7688         }
7689         else
7690                 r_refdef.fogenabled = false;
7691
7692         switch(vid.renderpath)
7693         {
7694         case RENDERPATH_GL20:
7695         case RENDERPATH_CGGL:
7696                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7697                 {
7698                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7699                         {
7700                                 // build GLSL gamma texture
7701 #define RAMPWIDTH 256
7702                                 unsigned short ramp[RAMPWIDTH * 3];
7703                                 unsigned char rampbgr[RAMPWIDTH][4];
7704                                 int i;
7705
7706                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7707
7708                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7709                                 for(i = 0; i < RAMPWIDTH; ++i)
7710                                 {
7711                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7712                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7713                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7714                                         rampbgr[i][3] = 0;
7715                                 }
7716                                 if (r_texture_gammaramps)
7717                                 {
7718                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7719                                 }
7720                                 else
7721                                 {
7722                                         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);
7723                                 }
7724                         }
7725                 }
7726                 else
7727                 {
7728                         // remove GLSL gamma texture
7729                 }
7730                 break;
7731         case RENDERPATH_GL13:
7732         case RENDERPATH_GL11:
7733                 break;
7734         }
7735 }
7736
7737 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7738 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7739 /*
7740 ================
7741 R_SelectScene
7742 ================
7743 */
7744 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7745         if( scenetype != r_currentscenetype ) {
7746                 // store the old scenetype
7747                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7748                 r_currentscenetype = scenetype;
7749                 // move in the new scene
7750                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7751         }
7752 }
7753
7754 /*
7755 ================
7756 R_GetScenePointer
7757 ================
7758 */
7759 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7760 {
7761         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7762         if( scenetype == r_currentscenetype ) {
7763                 return &r_refdef.scene;
7764         } else {
7765                 return &r_scenes_store[ scenetype ];
7766         }
7767 }
7768
7769 /*
7770 ================
7771 R_RenderView
7772 ================
7773 */
7774 void R_RenderView(void)
7775 {
7776         if (r_timereport_active)
7777                 R_TimeReport("start");
7778         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7779
7780         if (!r_drawentities.integer)
7781                 r_refdef.scene.numentities = 0;
7782
7783         R_AnimCache_ClearCache();
7784         R_FrameData_NewFrame();
7785
7786         if (r_refdef.view.isoverlay)
7787         {
7788                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7789                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7790                 R_TimeReport("depthclear");
7791
7792                 r_refdef.view.showdebug = false;
7793
7794                 r_waterstate.enabled = false;
7795                 r_waterstate.numwaterplanes = 0;
7796
7797                 R_RenderScene();
7798
7799                 CHECKGLERROR
7800                 return;
7801         }
7802
7803         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7804                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7805
7806         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7807
7808         // break apart the view matrix into vectors for various purposes
7809         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7810         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7811         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7812         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7813         // make an inverted copy of the view matrix for tracking sprites
7814         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7815
7816         R_Shadow_UpdateWorldLightSelection();
7817
7818         R_Bloom_StartFrame();
7819         R_Water_StartFrame();
7820
7821         CHECKGLERROR
7822         if (r_timereport_active)
7823                 R_TimeReport("viewsetup");
7824
7825         R_ResetViewRendering3D();
7826
7827         if (r_refdef.view.clear || r_refdef.fogenabled)
7828         {
7829                 R_ClearScreen(r_refdef.fogenabled);
7830                 if (r_timereport_active)
7831                         R_TimeReport("viewclear");
7832         }
7833         r_refdef.view.clear = true;
7834
7835         // this produces a bloom texture to be used in R_BlendView() later
7836         if (r_hdr.integer && r_bloomstate.bloomwidth)
7837                 R_HDR_RenderBloomTexture();
7838
7839         r_refdef.view.showdebug = true;
7840
7841         R_View_Update();
7842         if (r_timereport_active)
7843                 R_TimeReport("visibility");
7844
7845         r_waterstate.numwaterplanes = 0;
7846         if (r_waterstate.enabled)
7847                 R_RenderWaterPlanes();
7848
7849         R_RenderScene();
7850         r_waterstate.numwaterplanes = 0;
7851
7852         R_BlendView();
7853         if (r_timereport_active)
7854                 R_TimeReport("blendview");
7855
7856         GL_Scissor(0, 0, vid.width, vid.height);
7857         GL_ScissorTest(false);
7858         CHECKGLERROR
7859 }
7860
7861 void R_RenderWaterPlanes(void)
7862 {
7863         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7864         {
7865                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7866                 if (r_timereport_active)
7867                         R_TimeReport("waterworld");
7868         }
7869
7870         // don't let sound skip if going slow
7871         if (r_refdef.scene.extraupdate)
7872                 S_ExtraUpdate ();
7873
7874         R_DrawModelsAddWaterPlanes();
7875         if (r_timereport_active)
7876                 R_TimeReport("watermodels");
7877
7878         if (r_waterstate.numwaterplanes)
7879         {
7880                 R_Water_ProcessPlanes();
7881                 if (r_timereport_active)
7882                         R_TimeReport("waterscenes");
7883         }
7884 }
7885
7886 extern void R_DrawLightningBeams (void);
7887 extern void VM_CL_AddPolygonsToMeshQueue (void);
7888 extern void R_DrawPortals (void);
7889 extern cvar_t cl_locs_show;
7890 static void R_DrawLocs(void);
7891 static void R_DrawEntityBBoxes(void);
7892 static void R_DrawModelDecals(void);
7893 extern cvar_t cl_decals_newsystem;
7894 extern qboolean r_shadow_usingdeferredprepass;
7895 void R_RenderScene(void)
7896 {
7897         r_refdef.stats.renders++;
7898         r_textureframe++; // used only by R_GetCurrentTexture
7899
7900         R_UpdateFogColor();
7901
7902         // don't let sound skip if going slow
7903         if (r_refdef.scene.extraupdate)
7904                 S_ExtraUpdate ();
7905
7906         R_MeshQueue_BeginScene();
7907
7908         R_SkyStartFrame();
7909
7910         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);
7911
7912         if (cl.csqc_vidvars.drawworld)
7913         {
7914                 // don't let sound skip if going slow
7915                 if (r_refdef.scene.extraupdate)
7916                         S_ExtraUpdate ();
7917
7918                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7919                 {
7920                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7921                         if (r_timereport_active)
7922                                 R_TimeReport("worldsky");
7923                 }
7924
7925                 if (R_DrawBrushModelsSky() && r_timereport_active)
7926                         R_TimeReport("bmodelsky");
7927
7928                 if (skyrendermasked && skyrenderlater)
7929                 {
7930                         // we have to force off the water clipping plane while rendering sky
7931                         R_SetupView(false);
7932                         R_Sky();
7933                         R_SetupView(true);
7934                         if (r_timereport_active)
7935                                 R_TimeReport("sky");
7936                 }
7937         }
7938
7939         R_AnimCache_CacheVisibleEntities();
7940         if (r_timereport_active)
7941                 R_TimeReport("animation");
7942
7943         R_Shadow_PrepareLights();
7944         if (r_timereport_active)
7945                 R_TimeReport("preparelights");
7946
7947         if (r_shadow_usingdeferredprepass)
7948                 R_Shadow_DrawPrepass();
7949
7950         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7951         {
7952                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7953                 if (r_timereport_active)
7954                         R_TimeReport("worlddepth");
7955         }
7956         if (r_depthfirst.integer >= 2)
7957         {
7958                 R_DrawModelsDepth();
7959                 if (r_timereport_active)
7960                         R_TimeReport("modeldepth");
7961         }
7962
7963         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7964         {
7965                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7966                 if (r_timereport_active)
7967                         R_TimeReport("world");
7968         }
7969
7970         // don't let sound skip if going slow
7971         if (r_refdef.scene.extraupdate)
7972                 S_ExtraUpdate ();
7973
7974         R_DrawModels();
7975         if (r_timereport_active)
7976                 R_TimeReport("models");
7977
7978         // don't let sound skip if going slow
7979         if (r_refdef.scene.extraupdate)
7980                 S_ExtraUpdate ();
7981
7982         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7983         {
7984                 R_DrawModelShadows();
7985                 R_ResetViewRendering3D();
7986                 // don't let sound skip if going slow
7987                 if (r_refdef.scene.extraupdate)
7988                         S_ExtraUpdate ();
7989         }
7990
7991         if (!r_shadow_usingdeferredprepass)
7992         {
7993                 R_Shadow_DrawLights();
7994                 if (r_timereport_active)
7995                         R_TimeReport("rtlights");
7996         }
7997
7998         // don't let sound skip if going slow
7999         if (r_refdef.scene.extraupdate)
8000                 S_ExtraUpdate ();
8001
8002         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8003         {
8004                 R_DrawModelShadows();
8005                 R_ResetViewRendering3D();
8006                 // don't let sound skip if going slow
8007                 if (r_refdef.scene.extraupdate)
8008                         S_ExtraUpdate ();
8009         }
8010
8011         if (cl.csqc_vidvars.drawworld)
8012         {
8013                 if (cl_decals_newsystem.integer)
8014                 {
8015                         R_DrawModelDecals();
8016                         if (r_timereport_active)
8017                                 R_TimeReport("modeldecals");
8018                 }
8019                 else
8020                 {
8021                         R_DrawDecals();
8022                         if (r_timereport_active)
8023                                 R_TimeReport("decals");
8024                 }
8025
8026                 R_DrawParticles();
8027                 if (r_timereport_active)
8028                         R_TimeReport("particles");
8029
8030                 R_DrawExplosions();
8031                 if (r_timereport_active)
8032                         R_TimeReport("explosions");
8033
8034                 R_DrawLightningBeams();
8035                 if (r_timereport_active)
8036                         R_TimeReport("lightning");
8037         }
8038
8039         VM_CL_AddPolygonsToMeshQueue();
8040
8041         if (r_refdef.view.showdebug)
8042         {
8043                 if (cl_locs_show.integer)
8044                 {
8045                         R_DrawLocs();
8046                         if (r_timereport_active)
8047                                 R_TimeReport("showlocs");
8048                 }
8049
8050                 if (r_drawportals.integer)
8051                 {
8052                         R_DrawPortals();
8053                         if (r_timereport_active)
8054                                 R_TimeReport("portals");
8055                 }
8056
8057                 if (r_showbboxes.value > 0)
8058                 {
8059                         R_DrawEntityBBoxes();
8060                         if (r_timereport_active)
8061                                 R_TimeReport("bboxes");
8062                 }
8063         }
8064
8065         R_MeshQueue_RenderTransparent();
8066         if (r_timereport_active)
8067                 R_TimeReport("drawtrans");
8068
8069         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))
8070         {
8071                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8072                 if (r_timereport_active)
8073                         R_TimeReport("worlddebug");
8074                 R_DrawModelsDebug();
8075                 if (r_timereport_active)
8076                         R_TimeReport("modeldebug");
8077         }
8078
8079         if (cl.csqc_vidvars.drawworld)
8080         {
8081                 R_Shadow_DrawCoronas();
8082                 if (r_timereport_active)
8083                         R_TimeReport("coronas");
8084         }
8085
8086         // don't let sound skip if going slow
8087         if (r_refdef.scene.extraupdate)
8088                 S_ExtraUpdate ();
8089
8090         R_ResetViewRendering2D();
8091 }
8092
8093 static const unsigned short bboxelements[36] =
8094 {
8095         5, 1, 3, 5, 3, 7,
8096         6, 2, 0, 6, 0, 4,
8097         7, 3, 2, 7, 2, 6,
8098         4, 0, 1, 4, 1, 5,
8099         4, 5, 7, 4, 7, 6,
8100         1, 0, 2, 1, 2, 3,
8101 };
8102
8103 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8104 {
8105         int i;
8106         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8107
8108         RSurf_ActiveWorldEntity();
8109
8110         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8111         GL_DepthMask(false);
8112         GL_DepthRange(0, 1);
8113         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8114         R_Mesh_ResetTextureState();
8115
8116         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8117         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8118         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8119         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8120         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8121         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8122         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8123         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8124         R_FillColors(color4f, 8, cr, cg, cb, ca);
8125         if (r_refdef.fogenabled)
8126         {
8127                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8128                 {
8129                         f1 = RSurf_FogVertex(v);
8130                         f2 = 1 - f1;
8131                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8132                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8133                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8134                 }
8135         }
8136         R_Mesh_VertexPointer(vertex3f, 0, 0);
8137         R_Mesh_ColorPointer(color4f, 0, 0);
8138         R_Mesh_ResetTextureState();
8139         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8140         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8141 }
8142
8143 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8144 {
8145         int i;
8146         float color[4];
8147         prvm_edict_t *edict;
8148         prvm_prog_t *prog_save = prog;
8149
8150         // this function draws bounding boxes of server entities
8151         if (!sv.active)
8152                 return;
8153
8154         GL_CullFace(GL_NONE);
8155         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8156
8157         prog = 0;
8158         SV_VM_Begin();
8159         for (i = 0;i < numsurfaces;i++)
8160         {
8161                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8162                 switch ((int)edict->fields.server->solid)
8163                 {
8164                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8165                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8166                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8167                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8168                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8169                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8170                 }
8171                 color[3] *= r_showbboxes.value;
8172                 color[3] = bound(0, color[3], 1);
8173                 GL_DepthTest(!r_showdisabledepthtest.integer);
8174                 GL_CullFace(r_refdef.view.cullface_front);
8175                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8176         }
8177         SV_VM_End();
8178         prog = prog_save;
8179 }
8180
8181 static void R_DrawEntityBBoxes(void)
8182 {
8183         int i;
8184         prvm_edict_t *edict;
8185         vec3_t center;
8186         prvm_prog_t *prog_save = prog;
8187
8188         // this function draws bounding boxes of server entities
8189         if (!sv.active)
8190                 return;
8191
8192         prog = 0;
8193         SV_VM_Begin();
8194         for (i = 0;i < prog->num_edicts;i++)
8195         {
8196                 edict = PRVM_EDICT_NUM(i);
8197                 if (edict->priv.server->free)
8198                         continue;
8199                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8200                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8201                         continue;
8202                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8203                         continue;
8204                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8205                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8206         }
8207         SV_VM_End();
8208         prog = prog_save;
8209 }
8210
8211 static const int nomodelelement3i[24] =
8212 {
8213         5, 2, 0,
8214         5, 1, 2,
8215         5, 0, 3,
8216         5, 3, 1,
8217         0, 2, 4,
8218         2, 1, 4,
8219         3, 0, 4,
8220         1, 3, 4
8221 };
8222
8223 static const unsigned short nomodelelement3s[24] =
8224 {
8225         5, 2, 0,
8226         5, 1, 2,
8227         5, 0, 3,
8228         5, 3, 1,
8229         0, 2, 4,
8230         2, 1, 4,
8231         3, 0, 4,
8232         1, 3, 4
8233 };
8234
8235 static const float nomodelvertex3f[6*3] =
8236 {
8237         -16,   0,   0,
8238          16,   0,   0,
8239           0, -16,   0,
8240           0,  16,   0,
8241           0,   0, -16,
8242           0,   0,  16
8243 };
8244
8245 static const float nomodelcolor4f[6*4] =
8246 {
8247         0.0f, 0.0f, 0.5f, 1.0f,
8248         0.0f, 0.0f, 0.5f, 1.0f,
8249         0.0f, 0.5f, 0.0f, 1.0f,
8250         0.0f, 0.5f, 0.0f, 1.0f,
8251         0.5f, 0.0f, 0.0f, 1.0f,
8252         0.5f, 0.0f, 0.0f, 1.0f
8253 };
8254
8255 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8256 {
8257         int i;
8258         float f1, f2, *c;
8259         float color4f[6*4];
8260
8261         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);
8262
8263         // this is only called once per entity so numsurfaces is always 1, and
8264         // surfacelist is always {0}, so this code does not handle batches
8265
8266         if (rsurface.ent_flags & RENDER_ADDITIVE)
8267         {
8268                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8269                 GL_DepthMask(false);
8270         }
8271         else if (rsurface.colormod[3] < 1)
8272         {
8273                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8274                 GL_DepthMask(false);
8275         }
8276         else
8277         {
8278                 GL_BlendFunc(GL_ONE, GL_ZERO);
8279                 GL_DepthMask(true);
8280         }
8281         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8282         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8283         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8284         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8285         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8286         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8287         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8288         R_Mesh_ColorPointer(color4f, 0, 0);
8289         for (i = 0, c = color4f;i < 6;i++, c += 4)
8290         {
8291                 c[0] *= rsurface.colormod[0];
8292                 c[1] *= rsurface.colormod[1];
8293                 c[2] *= rsurface.colormod[2];
8294                 c[3] *= rsurface.colormod[3];
8295         }
8296         if (r_refdef.fogenabled)
8297         {
8298                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8299                 {
8300                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8301                         f2 = 1 - f1;
8302                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8303                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8304                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8305                 }
8306         }
8307         R_Mesh_ResetTextureState();
8308         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8309 }
8310
8311 void R_DrawNoModel(entity_render_t *ent)
8312 {
8313         vec3_t org;
8314         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8315         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8316                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8317         else
8318                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8319 }
8320
8321 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8322 {
8323         vec3_t right1, right2, diff, normal;
8324
8325         VectorSubtract (org2, org1, normal);
8326
8327         // calculate 'right' vector for start
8328         VectorSubtract (r_refdef.view.origin, org1, diff);
8329         CrossProduct (normal, diff, right1);
8330         VectorNormalize (right1);
8331
8332         // calculate 'right' vector for end
8333         VectorSubtract (r_refdef.view.origin, org2, diff);
8334         CrossProduct (normal, diff, right2);
8335         VectorNormalize (right2);
8336
8337         vert[ 0] = org1[0] + width * right1[0];
8338         vert[ 1] = org1[1] + width * right1[1];
8339         vert[ 2] = org1[2] + width * right1[2];
8340         vert[ 3] = org1[0] - width * right1[0];
8341         vert[ 4] = org1[1] - width * right1[1];
8342         vert[ 5] = org1[2] - width * right1[2];
8343         vert[ 6] = org2[0] - width * right2[0];
8344         vert[ 7] = org2[1] - width * right2[1];
8345         vert[ 8] = org2[2] - width * right2[2];
8346         vert[ 9] = org2[0] + width * right2[0];
8347         vert[10] = org2[1] + width * right2[1];
8348         vert[11] = org2[2] + width * right2[2];
8349 }
8350
8351 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)
8352 {
8353         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8354         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8355         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8356         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8357         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8358         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8359         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8360         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8361         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8362         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8363         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8364         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8365 }
8366
8367 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8368 {
8369         int i;
8370         float *vertex3f;
8371         float v[3];
8372         VectorSet(v, x, y, z);
8373         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8374                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8375                         break;
8376         if (i == mesh->numvertices)
8377         {
8378                 if (mesh->numvertices < mesh->maxvertices)
8379                 {
8380                         VectorCopy(v, vertex3f);
8381                         mesh->numvertices++;
8382                 }
8383                 return mesh->numvertices;
8384         }
8385         else
8386                 return i;
8387 }
8388
8389 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8390 {
8391         int i;
8392         int *e, element[3];
8393         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8394         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8395         e = mesh->element3i + mesh->numtriangles * 3;
8396         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8397         {
8398                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8399                 if (mesh->numtriangles < mesh->maxtriangles)
8400                 {
8401                         *e++ = element[0];
8402                         *e++ = element[1];
8403                         *e++ = element[2];
8404                         mesh->numtriangles++;
8405                 }
8406                 element[1] = element[2];
8407         }
8408 }
8409
8410 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8411 {
8412         int i;
8413         int *e, element[3];
8414         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8415         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8416         e = mesh->element3i + mesh->numtriangles * 3;
8417         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8418         {
8419                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8420                 if (mesh->numtriangles < mesh->maxtriangles)
8421                 {
8422                         *e++ = element[0];
8423                         *e++ = element[1];
8424                         *e++ = element[2];
8425                         mesh->numtriangles++;
8426                 }
8427                 element[1] = element[2];
8428         }
8429 }
8430
8431 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8432 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8433 {
8434         int planenum, planenum2;
8435         int w;
8436         int tempnumpoints;
8437         mplane_t *plane, *plane2;
8438         double maxdist;
8439         double temppoints[2][256*3];
8440         // figure out how large a bounding box we need to properly compute this brush
8441         maxdist = 0;
8442         for (w = 0;w < numplanes;w++)
8443                 maxdist = max(maxdist, fabs(planes[w].dist));
8444         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8445         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8446         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8447         {
8448                 w = 0;
8449                 tempnumpoints = 4;
8450                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8451                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8452                 {
8453                         if (planenum2 == planenum)
8454                                 continue;
8455                         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);
8456                         w = !w;
8457                 }
8458                 if (tempnumpoints < 3)
8459                         continue;
8460                 // generate elements forming a triangle fan for this polygon
8461                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8462         }
8463 }
8464
8465 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)
8466 {
8467         texturelayer_t *layer;
8468         layer = t->currentlayers + t->currentnumlayers++;
8469         layer->type = type;
8470         layer->depthmask = depthmask;
8471         layer->blendfunc1 = blendfunc1;
8472         layer->blendfunc2 = blendfunc2;
8473         layer->texture = texture;
8474         layer->texmatrix = *matrix;
8475         layer->color[0] = r;
8476         layer->color[1] = g;
8477         layer->color[2] = b;
8478         layer->color[3] = a;
8479 }
8480
8481 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8482 {
8483         double index, f;
8484         index = parms[2] + r_refdef.scene.time * parms[3];
8485         index -= floor(index);
8486         switch (func)
8487         {
8488         default:
8489         case Q3WAVEFUNC_NONE:
8490         case Q3WAVEFUNC_NOISE:
8491         case Q3WAVEFUNC_COUNT:
8492                 f = 0;
8493                 break;
8494         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8495         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8496         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8497         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8498         case Q3WAVEFUNC_TRIANGLE:
8499                 index *= 4;
8500                 f = index - floor(index);
8501                 if (index < 1)
8502                         f = f;
8503                 else if (index < 2)
8504                         f = 1 - f;
8505                 else if (index < 3)
8506                         f = -f;
8507                 else
8508                         f = -(1 - f);
8509                 break;
8510         }
8511         return (float)(parms[0] + parms[1] * f);
8512 }
8513
8514 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8515 {
8516         int w, h, idx;
8517         float f;
8518         float tcmat[12];
8519         matrix4x4_t matrix, temp;
8520         switch(tcmod->tcmod)
8521         {
8522                 case Q3TCMOD_COUNT:
8523                 case Q3TCMOD_NONE:
8524                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8525                                 matrix = r_waterscrollmatrix;
8526                         else
8527                                 matrix = identitymatrix;
8528                         break;
8529                 case Q3TCMOD_ENTITYTRANSLATE:
8530                         // this is used in Q3 to allow the gamecode to control texcoord
8531                         // scrolling on the entity, which is not supported in darkplaces yet.
8532                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8533                         break;
8534                 case Q3TCMOD_ROTATE:
8535                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8536                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8537                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8538                         break;
8539                 case Q3TCMOD_SCALE:
8540                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8541                         break;
8542                 case Q3TCMOD_SCROLL:
8543                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8544                         break;
8545                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8546                         w = (int) tcmod->parms[0];
8547                         h = (int) tcmod->parms[1];
8548                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8549                         f = f - floor(f);
8550                         idx = (int) floor(f * w * h);
8551                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8552                         break;
8553                 case Q3TCMOD_STRETCH:
8554                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8555                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8556                         break;
8557                 case Q3TCMOD_TRANSFORM:
8558                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8559                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8560                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8561                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8562                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8563                         break;
8564                 case Q3TCMOD_TURBULENT:
8565                         // this is handled in the RSurf_PrepareVertices function
8566                         matrix = identitymatrix;
8567                         break;
8568         }
8569         temp = *texmatrix;
8570         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8571 }
8572
8573 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8574 {
8575         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8576         char name[MAX_QPATH];
8577         skinframe_t *skinframe;
8578         unsigned char pixels[296*194];
8579         strlcpy(cache->name, skinname, sizeof(cache->name));
8580         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8581         if (developer_loading.integer)
8582                 Con_Printf("loading %s\n", name);
8583         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8584         if (!skinframe || !skinframe->base)
8585         {
8586                 unsigned char *f;
8587                 fs_offset_t filesize;
8588                 skinframe = NULL;
8589                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8590                 if (f)
8591                 {
8592                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8593                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8594                         Mem_Free(f);
8595                 }
8596         }
8597         cache->skinframe = skinframe;
8598 }
8599
8600 texture_t *R_GetCurrentTexture(texture_t *t)
8601 {
8602         int i;
8603         const entity_render_t *ent = rsurface.entity;
8604         dp_model_t *model = ent->model;
8605         q3shaderinfo_layer_tcmod_t *tcmod;
8606
8607         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8608                 return t->currentframe;
8609         t->update_lastrenderframe = r_textureframe;
8610         t->update_lastrenderentity = (void *)ent;
8611
8612         // switch to an alternate material if this is a q1bsp animated material
8613         {
8614                 texture_t *texture = t;
8615                 int s = rsurface.ent_skinnum;
8616                 if ((unsigned int)s >= (unsigned int)model->numskins)
8617                         s = 0;
8618                 if (model->skinscenes)
8619                 {
8620                         if (model->skinscenes[s].framecount > 1)
8621                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8622                         else
8623                                 s = model->skinscenes[s].firstframe;
8624                 }
8625                 if (s > 0)
8626                         t = t + s * model->num_surfaces;
8627                 if (t->animated)
8628                 {
8629                         // use an alternate animation if the entity's frame is not 0,
8630                         // and only if the texture has an alternate animation
8631                         if (rsurface.ent_alttextures && t->anim_total[1])
8632                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8633                         else
8634                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8635                 }
8636                 texture->currentframe = t;
8637         }
8638
8639         // update currentskinframe to be a qw skin or animation frame
8640         if (rsurface.ent_qwskin >= 0)
8641         {
8642                 i = rsurface.ent_qwskin;
8643                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8644                 {
8645                         r_qwskincache_size = cl.maxclients;
8646                         if (r_qwskincache)
8647                                 Mem_Free(r_qwskincache);
8648                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8649                 }
8650                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8651                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8652                 t->currentskinframe = r_qwskincache[i].skinframe;
8653                 if (t->currentskinframe == NULL)
8654                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8655         }
8656         else if (t->numskinframes >= 2)
8657                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8658         if (t->backgroundnumskinframes >= 2)
8659                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8660
8661         t->currentmaterialflags = t->basematerialflags;
8662         t->currentalpha = rsurface.colormod[3];
8663         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8664                 t->currentalpha *= r_wateralpha.value;
8665         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8666                 t->currentalpha *= t->r_water_wateralpha;
8667         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8668                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8669         if (!(rsurface.ent_flags & RENDER_LIGHT))
8670                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8671         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8672         {
8673                 // pick a model lighting mode
8674                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8675                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8676                 else
8677                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8678         }
8679         if (rsurface.ent_flags & RENDER_ADDITIVE)
8680                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8681         else if (t->currentalpha < 1)
8682                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8683         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8684                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8685         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8686                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8687         if (t->backgroundnumskinframes)
8688                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8689         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8690         {
8691                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8692                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8693         }
8694         else
8695                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8696         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8697                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8698
8699         // there is no tcmod
8700         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8701         {
8702                 t->currenttexmatrix = r_waterscrollmatrix;
8703                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8704         }
8705         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8706         {
8707                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8708                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8709         }
8710
8711         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8712                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8713         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8714                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8715
8716         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8717         if (t->currentskinframe->qpixels)
8718                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8719         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8720         if (!t->basetexture)
8721                 t->basetexture = r_texture_notexture;
8722         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8723         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8724         t->nmaptexture = t->currentskinframe->nmap;
8725         if (!t->nmaptexture)
8726                 t->nmaptexture = r_texture_blanknormalmap;
8727         t->glosstexture = r_texture_black;
8728         t->glowtexture = t->currentskinframe->glow;
8729         t->fogtexture = t->currentskinframe->fog;
8730         if (t->backgroundnumskinframes)
8731         {
8732                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8733                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8734                 t->backgroundglosstexture = r_texture_black;
8735                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8736                 if (!t->backgroundnmaptexture)
8737                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8738         }
8739         else
8740         {
8741                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8742                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8743                 t->backgroundglosstexture = r_texture_black;
8744                 t->backgroundglowtexture = NULL;
8745         }
8746         t->specularpower = r_shadow_glossexponent.value;
8747         // TODO: store reference values for these in the texture?
8748         t->specularscale = 0;
8749         if (r_shadow_gloss.integer > 0)
8750         {
8751                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8752                 {
8753                         if (r_shadow_glossintensity.value > 0)
8754                         {
8755                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8756                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8757                                 t->specularscale = r_shadow_glossintensity.value;
8758                         }
8759                 }
8760                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8761                 {
8762                         t->glosstexture = r_texture_white;
8763                         t->backgroundglosstexture = r_texture_white;
8764                         t->specularscale = r_shadow_gloss2intensity.value;
8765                         t->specularpower = r_shadow_gloss2exponent.value;
8766                 }
8767         }
8768         t->specularscale *= t->specularscalemod;
8769         t->specularpower *= t->specularpowermod;
8770
8771         // lightmaps mode looks bad with dlights using actual texturing, so turn
8772         // off the colormap and glossmap, but leave the normalmap on as it still
8773         // accurately represents the shading involved
8774         if (gl_lightmaps.integer)
8775         {
8776                 t->basetexture = r_texture_grey128;
8777                 t->pantstexture = r_texture_black;
8778                 t->shirttexture = r_texture_black;
8779                 t->nmaptexture = r_texture_blanknormalmap;
8780                 t->glosstexture = r_texture_black;
8781                 t->glowtexture = NULL;
8782                 t->fogtexture = NULL;
8783                 t->backgroundbasetexture = NULL;
8784                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8785                 t->backgroundglosstexture = r_texture_black;
8786                 t->backgroundglowtexture = NULL;
8787                 t->specularscale = 0;
8788                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8789         }
8790
8791         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8792         VectorClear(t->dlightcolor);
8793         t->currentnumlayers = 0;
8794         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8795         {
8796                 int blendfunc1, blendfunc2;
8797                 qboolean depthmask;
8798                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8799                 {
8800                         blendfunc1 = GL_SRC_ALPHA;
8801                         blendfunc2 = GL_ONE;
8802                 }
8803                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8804                 {
8805                         blendfunc1 = GL_SRC_ALPHA;
8806                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8807                 }
8808                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8809                 {
8810                         blendfunc1 = t->customblendfunc[0];
8811                         blendfunc2 = t->customblendfunc[1];
8812                 }
8813                 else
8814                 {
8815                         blendfunc1 = GL_ONE;
8816                         blendfunc2 = GL_ZERO;
8817                 }
8818                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8819                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8820                 {
8821                         // fullbright is not affected by r_refdef.lightmapintensity
8822                         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]);
8823                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8824                                 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]);
8825                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8826                                 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]);
8827                 }
8828                 else
8829                 {
8830                         vec3_t ambientcolor;
8831                         float colorscale;
8832                         // set the color tint used for lights affecting this surface
8833                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8834                         colorscale = 2;
8835                         // q3bsp has no lightmap updates, so the lightstylevalue that
8836                         // would normally be baked into the lightmap must be
8837                         // applied to the color
8838                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8839                         if (model->type == mod_brushq3)
8840                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8841                         colorscale *= r_refdef.lightmapintensity;
8842                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8843                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8844                         // basic lit geometry
8845                         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]);
8846                         // add pants/shirt if needed
8847                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8848                                 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]);
8849                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8850                                 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]);
8851                         // now add ambient passes if needed
8852                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8853                         {
8854                                 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]);
8855                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8856                                         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]);
8857                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8858                                         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]);
8859                         }
8860                 }
8861                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8862                         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]);
8863                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8864                 {
8865                         // if this is opaque use alpha blend which will darken the earlier
8866                         // passes cheaply.
8867                         //
8868                         // if this is an alpha blended material, all the earlier passes
8869                         // were darkened by fog already, so we only need to add the fog
8870                         // color ontop through the fog mask texture
8871                         //
8872                         // if this is an additive blended material, all the earlier passes
8873                         // were darkened by fog already, and we should not add fog color
8874                         // (because the background was not darkened, there is no fog color
8875                         // that was lost behind it).
8876                         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]);
8877                 }
8878         }
8879
8880         return t->currentframe;
8881 }
8882
8883 rsurfacestate_t rsurface;
8884
8885 void R_Mesh_ResizeArrays(int newvertices)
8886 {
8887         float *base;
8888         if (rsurface.array_size >= newvertices)
8889                 return;
8890         if (rsurface.array_modelvertex3f)
8891                 Mem_Free(rsurface.array_modelvertex3f);
8892         rsurface.array_size = (newvertices + 1023) & ~1023;
8893         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8894         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8895         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8896         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8897         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8898         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8899         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8900         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8901         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8902         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8903         rsurface.array_color4f           = base + rsurface.array_size * 27;
8904         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8905 }
8906
8907 void RSurf_ActiveWorldEntity(void)
8908 {
8909         dp_model_t *model = r_refdef.scene.worldmodel;
8910         //if (rsurface.entity == r_refdef.scene.worldentity)
8911         //      return;
8912         rsurface.entity = r_refdef.scene.worldentity;
8913         rsurface.skeleton = NULL;
8914         rsurface.ent_skinnum = 0;
8915         rsurface.ent_qwskin = -1;
8916         rsurface.ent_shadertime = 0;
8917         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8918         if (rsurface.array_size < model->surfmesh.num_vertices)
8919                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8920         rsurface.matrix = identitymatrix;
8921         rsurface.inversematrix = identitymatrix;
8922         rsurface.matrixscale = 1;
8923         rsurface.inversematrixscale = 1;
8924         R_EntityMatrix(&identitymatrix);
8925         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8926         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8927         rsurface.fograngerecip = r_refdef.fograngerecip;
8928         rsurface.fogheightfade = r_refdef.fogheightfade;
8929         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8930         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8931         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8932         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8933         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8934         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8935         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8936         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8937         rsurface.colormod[3] = 1;
8938         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);
8939         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8940         rsurface.frameblend[0].lerp = 1;
8941         rsurface.ent_alttextures = false;
8942         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8943         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8944         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8945         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8946         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8947         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8948         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8949         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8950         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8951         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8952         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8953         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8954         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8955         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8956         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8957         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8958         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8959         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8960         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8961         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8962         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8963         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8964         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8965         rsurface.modelelement3i = model->surfmesh.data_element3i;
8966         rsurface.modelelement3s = model->surfmesh.data_element3s;
8967         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8968         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8969         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8970         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8971         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8972         rsurface.modelsurfaces = model->data_surfaces;
8973         rsurface.generatedvertex = false;
8974         rsurface.vertex3f  = rsurface.modelvertex3f;
8975         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8976         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8977         rsurface.svector3f = rsurface.modelsvector3f;
8978         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8979         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8980         rsurface.tvector3f = rsurface.modeltvector3f;
8981         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8982         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8983         rsurface.normal3f  = rsurface.modelnormal3f;
8984         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8985         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8986         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8987 }
8988
8989 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8990 {
8991         dp_model_t *model = ent->model;
8992         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8993         //      return;
8994         rsurface.entity = (entity_render_t *)ent;
8995         rsurface.skeleton = ent->skeleton;
8996         rsurface.ent_skinnum = ent->skinnum;
8997         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;
8998         rsurface.ent_shadertime = ent->shadertime;
8999         rsurface.ent_flags = ent->flags;
9000         if (rsurface.array_size < model->surfmesh.num_vertices)
9001                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9002         rsurface.matrix = ent->matrix;
9003         rsurface.inversematrix = ent->inversematrix;
9004         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9005         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9006         R_EntityMatrix(&rsurface.matrix);
9007         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9008         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9009         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9010         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9011         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9012         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9013         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9014         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9015         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9016         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9017         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9018         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9019         rsurface.colormod[3] = ent->alpha;
9020         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9021         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9022         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9023         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9024         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9025         if (ent->model->brush.submodel && !prepass)
9026         {
9027                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9028                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9029         }
9030         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9031         {
9032                 if (ent->animcache_vertex3f && !r_framedata_failed)
9033                 {
9034                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9035                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9036                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9037                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9038                 }
9039                 else if (wanttangents)
9040                 {
9041                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9042                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9043                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9044                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9045                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9046                 }
9047                 else if (wantnormals)
9048                 {
9049                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9050                         rsurface.modelsvector3f = NULL;
9051                         rsurface.modeltvector3f = NULL;
9052                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9053                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9054                 }
9055                 else
9056                 {
9057                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9058                         rsurface.modelsvector3f = NULL;
9059                         rsurface.modeltvector3f = NULL;
9060                         rsurface.modelnormal3f = NULL;
9061                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9062                 }
9063                 rsurface.modelvertex3f_bufferobject = 0;
9064                 rsurface.modelvertex3f_bufferoffset = 0;
9065                 rsurface.modelsvector3f_bufferobject = 0;
9066                 rsurface.modelsvector3f_bufferoffset = 0;
9067                 rsurface.modeltvector3f_bufferobject = 0;
9068                 rsurface.modeltvector3f_bufferoffset = 0;
9069                 rsurface.modelnormal3f_bufferobject = 0;
9070                 rsurface.modelnormal3f_bufferoffset = 0;
9071                 rsurface.generatedvertex = true;
9072         }
9073         else
9074         {
9075                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9076                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9077                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9078                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9079                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9080                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9081                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9082                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9083                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9084                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9085                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9086                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9087                 rsurface.generatedvertex = false;
9088         }
9089         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9090         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9091         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9092         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9093         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9094         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9095         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9096         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9097         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9098         rsurface.modelelement3i = model->surfmesh.data_element3i;
9099         rsurface.modelelement3s = model->surfmesh.data_element3s;
9100         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9101         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9102         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9103         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9104         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9105         rsurface.modelsurfaces = model->data_surfaces;
9106         rsurface.vertex3f  = rsurface.modelvertex3f;
9107         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9108         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9109         rsurface.svector3f = rsurface.modelsvector3f;
9110         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9111         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9112         rsurface.tvector3f = rsurface.modeltvector3f;
9113         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9114         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9115         rsurface.normal3f  = rsurface.modelnormal3f;
9116         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9117         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9118         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9119 }
9120
9121 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)
9122 {
9123         rsurface.entity = r_refdef.scene.worldentity;
9124         rsurface.skeleton = NULL;
9125         rsurface.ent_skinnum = 0;
9126         rsurface.ent_qwskin = -1;
9127         rsurface.ent_shadertime = shadertime;
9128         rsurface.ent_flags = entflags;
9129         rsurface.modelnum_vertices = numvertices;
9130         rsurface.modelnum_triangles = numtriangles;
9131         if (rsurface.array_size < rsurface.modelnum_vertices)
9132                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9133         rsurface.matrix = *matrix;
9134         rsurface.inversematrix = *inversematrix;
9135         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9136         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9137         R_EntityMatrix(&rsurface.matrix);
9138         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9139         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9140         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9141         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9142         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9143         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9144         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9145         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9146         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9147         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9148         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9149         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9150         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);
9151         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9152         rsurface.frameblend[0].lerp = 1;
9153         rsurface.ent_alttextures = false;
9154         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9155         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9156         if (wanttangents)
9157         {
9158                 rsurface.modelvertex3f = vertex3f;
9159                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9160                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9161                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9162         }
9163         else if (wantnormals)
9164         {
9165                 rsurface.modelvertex3f = vertex3f;
9166                 rsurface.modelsvector3f = NULL;
9167                 rsurface.modeltvector3f = NULL;
9168                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9169         }
9170         else
9171         {
9172                 rsurface.modelvertex3f = vertex3f;
9173                 rsurface.modelsvector3f = NULL;
9174                 rsurface.modeltvector3f = NULL;
9175                 rsurface.modelnormal3f = NULL;
9176         }
9177         rsurface.modelvertex3f_bufferobject = 0;
9178         rsurface.modelvertex3f_bufferoffset = 0;
9179         rsurface.modelsvector3f_bufferobject = 0;
9180         rsurface.modelsvector3f_bufferoffset = 0;
9181         rsurface.modeltvector3f_bufferobject = 0;
9182         rsurface.modeltvector3f_bufferoffset = 0;
9183         rsurface.modelnormal3f_bufferobject = 0;
9184         rsurface.modelnormal3f_bufferoffset = 0;
9185         rsurface.generatedvertex = true;
9186         rsurface.modellightmapcolor4f  = color4f;
9187         rsurface.modellightmapcolor4f_bufferobject = 0;
9188         rsurface.modellightmapcolor4f_bufferoffset = 0;
9189         rsurface.modeltexcoordtexture2f  = texcoord2f;
9190         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9191         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9192         rsurface.modeltexcoordlightmap2f  = NULL;
9193         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9194         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9195         rsurface.modelelement3i = element3i;
9196         rsurface.modelelement3s = element3s;
9197         rsurface.modelelement3i_bufferobject = 0;
9198         rsurface.modelelement3s_bufferobject = 0;
9199         rsurface.modellightmapoffsets = NULL;
9200         rsurface.modelsurfaces = NULL;
9201         rsurface.vertex3f  = rsurface.modelvertex3f;
9202         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9203         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9204         rsurface.svector3f = rsurface.modelsvector3f;
9205         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9206         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9207         rsurface.tvector3f = rsurface.modeltvector3f;
9208         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9209         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9210         rsurface.normal3f  = rsurface.modelnormal3f;
9211         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9212         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9213         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9214
9215         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9216         {
9217                 if ((wantnormals || wanttangents) && !normal3f)
9218                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9219                 if (wanttangents && !svector3f)
9220                         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);
9221         }
9222 }
9223
9224 float RSurf_FogPoint(const float *v)
9225 {
9226         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9227         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9228         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9229         float FogHeightFade = r_refdef.fogheightfade;
9230         float fogfrac;
9231         unsigned int fogmasktableindex;
9232         if (r_refdef.fogplaneviewabove)
9233                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9234         else
9235                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9236         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9237         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9238 }
9239
9240 float RSurf_FogVertex(const float *v)
9241 {
9242         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9243         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9244         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9245         float FogHeightFade = rsurface.fogheightfade;
9246         float fogfrac;
9247         unsigned int fogmasktableindex;
9248         if (r_refdef.fogplaneviewabove)
9249                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9250         else
9251                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9252         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9253         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9254 }
9255
9256 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9257 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9258 {
9259         int deformindex;
9260         int texturesurfaceindex;
9261         int i, j;
9262         float amplitude;
9263         float animpos;
9264         float scale;
9265         const float *v1, *in_tc;
9266         float *out_tc;
9267         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9268         float waveparms[4];
9269         q3shaderinfo_deform_t *deform;
9270         // 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
9271         if (rsurface.generatedvertex)
9272         {
9273                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9274                         generatenormals = true;
9275                 for (i = 0;i < Q3MAXDEFORMS;i++)
9276                 {
9277                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9278                         {
9279                                 generatetangents = true;
9280                                 generatenormals = true;
9281                         }
9282                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9283                                 generatenormals = true;
9284                 }
9285                 if (generatenormals && !rsurface.modelnormal3f)
9286                 {
9287                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9288                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9289                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9290                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9291                 }
9292                 if (generatetangents && !rsurface.modelsvector3f)
9293                 {
9294                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9295                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9296                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9297                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9298                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9299                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9300                         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);
9301                 }
9302         }
9303         rsurface.vertex3f  = rsurface.modelvertex3f;
9304         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9305         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9306         rsurface.svector3f = rsurface.modelsvector3f;
9307         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9308         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9309         rsurface.tvector3f = rsurface.modeltvector3f;
9310         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9311         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9312         rsurface.normal3f  = rsurface.modelnormal3f;
9313         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9314         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9315         // if vertices are deformed (sprite flares and things in maps, possibly
9316         // water waves, bulges and other deformations), generate them into
9317         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9318         // (may be static model data or generated data for an animated model, or
9319         //  the previous deform pass)
9320         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9321         {
9322                 switch (deform->deform)
9323                 {
9324                 default:
9325                 case Q3DEFORM_PROJECTIONSHADOW:
9326                 case Q3DEFORM_TEXT0:
9327                 case Q3DEFORM_TEXT1:
9328                 case Q3DEFORM_TEXT2:
9329                 case Q3DEFORM_TEXT3:
9330                 case Q3DEFORM_TEXT4:
9331                 case Q3DEFORM_TEXT5:
9332                 case Q3DEFORM_TEXT6:
9333                 case Q3DEFORM_TEXT7:
9334                 case Q3DEFORM_NONE:
9335                         break;
9336                 case Q3DEFORM_AUTOSPRITE:
9337                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9338                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9339                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9340                         VectorNormalize(newforward);
9341                         VectorNormalize(newright);
9342                         VectorNormalize(newup);
9343                         // make deformed versions of only the model vertices used by the specified surfaces
9344                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9345                         {
9346                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9347                                 // a single autosprite surface can contain multiple sprites...
9348                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9349                                 {
9350                                         VectorClear(center);
9351                                         for (i = 0;i < 4;i++)
9352                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9353                                         VectorScale(center, 0.25f, center);
9354                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9355                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9356                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9357                                         for (i = 0;i < 4;i++)
9358                                         {
9359                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9360                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9361                                         }
9362                                 }
9363                                 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);
9364                                 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);
9365                         }
9366                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9367                         rsurface.vertex3f_bufferobject = 0;
9368                         rsurface.vertex3f_bufferoffset = 0;
9369                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9370                         rsurface.svector3f_bufferobject = 0;
9371                         rsurface.svector3f_bufferoffset = 0;
9372                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9373                         rsurface.tvector3f_bufferobject = 0;
9374                         rsurface.tvector3f_bufferoffset = 0;
9375                         rsurface.normal3f = rsurface.array_deformednormal3f;
9376                         rsurface.normal3f_bufferobject = 0;
9377                         rsurface.normal3f_bufferoffset = 0;
9378                         break;
9379                 case Q3DEFORM_AUTOSPRITE2:
9380                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9381                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9382                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9383                         VectorNormalize(newforward);
9384                         VectorNormalize(newright);
9385                         VectorNormalize(newup);
9386                         // make deformed versions of only the model vertices used by the specified surfaces
9387                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9388                         {
9389                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9390                                 const float *v1, *v2;
9391                                 vec3_t start, end;
9392                                 float f, l;
9393                                 struct
9394                                 {
9395                                         float length2;
9396                                         const float *v1;
9397                                         const float *v2;
9398                                 }
9399                                 shortest[2];
9400                                 memset(shortest, 0, sizeof(shortest));
9401                                 // a single autosprite surface can contain multiple sprites...
9402                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9403                                 {
9404                                         VectorClear(center);
9405                                         for (i = 0;i < 4;i++)
9406                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9407                                         VectorScale(center, 0.25f, center);
9408                                         // find the two shortest edges, then use them to define the
9409                                         // axis vectors for rotating around the central axis
9410                                         for (i = 0;i < 6;i++)
9411                                         {
9412                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9413                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9414 #if 0
9415                                                 Debug_PolygonBegin(NULL, 0);
9416                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9417                                                 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);
9418                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9419                                                 Debug_PolygonEnd();
9420 #endif
9421                                                 l = VectorDistance2(v1, v2);
9422                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9423                                                 if (v1[2] != v2[2])
9424                                                         l += (1.0f / 1024.0f);
9425                                                 if (shortest[0].length2 > l || i == 0)
9426                                                 {
9427                                                         shortest[1] = shortest[0];
9428                                                         shortest[0].length2 = l;
9429                                                         shortest[0].v1 = v1;
9430                                                         shortest[0].v2 = v2;
9431                                                 }
9432                                                 else if (shortest[1].length2 > l || i == 1)
9433                                                 {
9434                                                         shortest[1].length2 = l;
9435                                                         shortest[1].v1 = v1;
9436                                                         shortest[1].v2 = v2;
9437                                                 }
9438                                         }
9439                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9440                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9441 #if 0
9442                                         Debug_PolygonBegin(NULL, 0);
9443                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9444                                         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);
9445                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9446                                         Debug_PolygonEnd();
9447 #endif
9448                                         // this calculates the right vector from the shortest edge
9449                                         // and the up vector from the edge midpoints
9450                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9451                                         VectorNormalize(right);
9452                                         VectorSubtract(end, start, up);
9453                                         VectorNormalize(up);
9454                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9455                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9456                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9457                                         VectorNegate(forward, forward);
9458                                         VectorReflect(forward, 0, up, forward);
9459                                         VectorNormalize(forward);
9460                                         CrossProduct(up, forward, newright);
9461                                         VectorNormalize(newright);
9462 #if 0
9463                                         Debug_PolygonBegin(NULL, 0);
9464                                         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);
9465                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9466                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9467                                         Debug_PolygonEnd();
9468 #endif
9469 #if 0
9470                                         Debug_PolygonBegin(NULL, 0);
9471                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9472                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9473                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9474                                         Debug_PolygonEnd();
9475 #endif
9476                                         // rotate the quad around the up axis vector, this is made
9477                                         // especially easy by the fact we know the quad is flat,
9478                                         // so we only have to subtract the center position and
9479                                         // measure distance along the right vector, and then
9480                                         // multiply that by the newright vector and add back the
9481                                         // center position
9482                                         // we also need to subtract the old position to undo the
9483                                         // displacement from the center, which we do with a
9484                                         // DotProduct, the subtraction/addition of center is also
9485                                         // optimized into DotProducts here
9486                                         l = DotProduct(right, center);
9487                                         for (i = 0;i < 4;i++)
9488                                         {
9489                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9490                                                 f = DotProduct(right, v1) - l;
9491                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9492                                         }
9493                                 }
9494                                 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);
9495                                 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);
9496                         }
9497                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9498                         rsurface.vertex3f_bufferobject = 0;
9499                         rsurface.vertex3f_bufferoffset = 0;
9500                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9501                         rsurface.svector3f_bufferobject = 0;
9502                         rsurface.svector3f_bufferoffset = 0;
9503                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9504                         rsurface.tvector3f_bufferobject = 0;
9505                         rsurface.tvector3f_bufferoffset = 0;
9506                         rsurface.normal3f = rsurface.array_deformednormal3f;
9507                         rsurface.normal3f_bufferobject = 0;
9508                         rsurface.normal3f_bufferoffset = 0;
9509                         break;
9510                 case Q3DEFORM_NORMAL:
9511                         // deform the normals to make reflections wavey
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[3];
9518                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9519                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9520                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9521                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9522                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9523                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9524                                         VectorNormalize(normal);
9525                                 }
9526                                 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);
9527                         }
9528                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9529                         rsurface.svector3f_bufferobject = 0;
9530                         rsurface.svector3f_bufferoffset = 0;
9531                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9532                         rsurface.tvector3f_bufferobject = 0;
9533                         rsurface.tvector3f_bufferoffset = 0;
9534                         rsurface.normal3f = rsurface.array_deformednormal3f;
9535                         rsurface.normal3f_bufferobject = 0;
9536                         rsurface.normal3f_bufferoffset = 0;
9537                         break;
9538                 case Q3DEFORM_WAVE:
9539                         // deform vertex array to make wavey water and flags and such
9540                         waveparms[0] = deform->waveparms[0];
9541                         waveparms[1] = deform->waveparms[1];
9542                         waveparms[2] = deform->waveparms[2];
9543                         waveparms[3] = deform->waveparms[3];
9544                         // this is how a divisor of vertex influence on deformation
9545                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9546                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9547                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9548                         {
9549                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9550                                 for (j = 0;j < surface->num_vertices;j++)
9551                                 {
9552                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9553                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9554                                         // if the wavefunc depends on time, evaluate it per-vertex
9555                                         if (waveparms[3])
9556                                         {
9557                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9558                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9559                                         }
9560                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9561                                 }
9562                         }
9563                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9564                         rsurface.vertex3f_bufferobject = 0;
9565                         rsurface.vertex3f_bufferoffset = 0;
9566                         break;
9567                 case Q3DEFORM_BULGE:
9568                         // deform vertex array to make the surface have moving bulges
9569                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9570                         {
9571                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9572                                 for (j = 0;j < surface->num_vertices;j++)
9573                                 {
9574                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9575                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9576                                 }
9577                         }
9578                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9579                         rsurface.vertex3f_bufferobject = 0;
9580                         rsurface.vertex3f_bufferoffset = 0;
9581                         break;
9582                 case Q3DEFORM_MOVE:
9583                         // deform vertex array
9584                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9585                         VectorScale(deform->parms, scale, waveparms);
9586                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9587                         {
9588                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9589                                 for (j = 0;j < surface->num_vertices;j++)
9590                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9591                         }
9592                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9593                         rsurface.vertex3f_bufferobject = 0;
9594                         rsurface.vertex3f_bufferoffset = 0;
9595                         break;
9596                 }
9597         }
9598         // generate texcoords based on the chosen texcoord source
9599         switch(rsurface.texture->tcgen.tcgen)
9600         {
9601         default:
9602         case Q3TCGEN_TEXTURE:
9603                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9604                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9605                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9606                 break;
9607         case Q3TCGEN_LIGHTMAP:
9608                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9609                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9610                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9611                 break;
9612         case Q3TCGEN_VECTOR:
9613                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9614                 {
9615                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9616                         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)
9617                         {
9618                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9619                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9620                         }
9621                 }
9622                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9623                 rsurface.texcoordtexture2f_bufferobject  = 0;
9624                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9625                 break;
9626         case Q3TCGEN_ENVIRONMENT:
9627                 // make environment reflections using a spheremap
9628                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9629                 {
9630                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9631                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9632                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9633                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9634                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9635                         {
9636                                 // identical to Q3A's method, but executed in worldspace so
9637                                 // carried models can be shiny too
9638
9639                                 float viewer[3], d, reflected[3], worldreflected[3];
9640
9641                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9642                                 // VectorNormalize(viewer);
9643
9644                                 d = DotProduct(normal, viewer);
9645
9646                                 reflected[0] = normal[0]*2*d - viewer[0];
9647                                 reflected[1] = normal[1]*2*d - viewer[1];
9648                                 reflected[2] = normal[2]*2*d - viewer[2];
9649                                 // note: this is proportinal to viewer, so we can normalize later
9650
9651                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9652                                 VectorNormalize(worldreflected);
9653
9654                                 // note: this sphere map only uses world x and z!
9655                                 // so positive and negative y will LOOK THE SAME.
9656                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9657                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9658                         }
9659                 }
9660                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9661                 rsurface.texcoordtexture2f_bufferobject  = 0;
9662                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9663                 break;
9664         }
9665         // the only tcmod that needs software vertex processing is turbulent, so
9666         // check for it here and apply the changes if needed
9667         // and we only support that as the first one
9668         // (handling a mixture of turbulent and other tcmods would be problematic
9669         //  without punting it entirely to a software path)
9670         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9671         {
9672                 amplitude = rsurface.texture->tcmods[0].parms[1];
9673                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9674                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9675                 {
9676                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9677                         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)
9678                         {
9679                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9680                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9681                         }
9682                 }
9683                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9684                 rsurface.texcoordtexture2f_bufferobject  = 0;
9685                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9686         }
9687         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9688         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9689         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9690         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9691 }
9692
9693 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9694 {
9695         int i, j;
9696         const msurface_t *surface = texturesurfacelist[0];
9697         const msurface_t *surface2;
9698         int firstvertex;
9699         int endvertex;
9700         int numvertices;
9701         int numtriangles;
9702         // TODO: lock all array ranges before render, rather than on each surface
9703         if (texturenumsurfaces == 1)
9704         {
9705                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9706                 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);
9707         }
9708         else if (r_batchmode.integer == 2)
9709         {
9710                 #define MAXBATCHTRIANGLES 4096
9711                 int batchtriangles = 0;
9712                 static int batchelements[MAXBATCHTRIANGLES*3];
9713                 for (i = 0;i < texturenumsurfaces;i = j)
9714                 {
9715                         surface = texturesurfacelist[i];
9716                         j = i + 1;
9717                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9718                         {
9719                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9720                                 continue;
9721                         }
9722                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9723                         batchtriangles = surface->num_triangles;
9724                         firstvertex = surface->num_firstvertex;
9725                         endvertex = surface->num_firstvertex + surface->num_vertices;
9726                         for (;j < texturenumsurfaces;j++)
9727                         {
9728                                 surface2 = texturesurfacelist[j];
9729                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9730                                         break;
9731                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9732                                 batchtriangles += surface2->num_triangles;
9733                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9734                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9735                         }
9736                         surface2 = texturesurfacelist[j-1];
9737                         numvertices = endvertex - firstvertex;
9738                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9739                 }
9740         }
9741         else if (r_batchmode.integer == 1)
9742         {
9743                 for (i = 0;i < texturenumsurfaces;i = j)
9744                 {
9745                         surface = texturesurfacelist[i];
9746                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9747                                 if (texturesurfacelist[j] != surface2)
9748                                         break;
9749                         surface2 = texturesurfacelist[j-1];
9750                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9751                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9752                         GL_LockArrays(surface->num_firstvertex, numvertices);
9753                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9754                 }
9755         }
9756         else
9757         {
9758                 for (i = 0;i < texturenumsurfaces;i++)
9759                 {
9760                         surface = texturesurfacelist[i];
9761                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9762                         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);
9763                 }
9764         }
9765 }
9766
9767 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9768 {
9769         switch(vid.renderpath)
9770         {
9771         case RENDERPATH_CGGL:
9772 #ifdef SUPPORTCG
9773                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9774                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9775 #endif
9776                 break;
9777         case RENDERPATH_GL20:
9778                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9779                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9780                 break;
9781         case RENDERPATH_GL13:
9782         case RENDERPATH_GL11:
9783                 R_Mesh_TexBind(0, surface->lightmaptexture);
9784                 break;
9785         }
9786 }
9787
9788 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9789 {
9790         // pick the closest matching water plane and bind textures
9791         int planeindex, vertexindex;
9792         float d, bestd;
9793         vec3_t vert;
9794         const float *v;
9795         r_waterstate_waterplane_t *p, *bestp;
9796         bestd = 0;
9797         bestp = NULL;
9798         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9799         {
9800                 d = 0;
9801                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9802                 {
9803                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9804                         d += fabs(PlaneDiff(vert, &p->plane));
9805                 }
9806                 if (bestd > d || !bestp)
9807                 {
9808                         bestd = d;
9809                         bestp = p;
9810                 }
9811         }
9812         switch(vid.renderpath)
9813         {
9814         case RENDERPATH_CGGL:
9815 #ifdef SUPPORTCG
9816                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9817                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9818 #endif
9819                 break;
9820         case RENDERPATH_GL20:
9821                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9822                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9823                 break;
9824         case RENDERPATH_GL13:
9825         case RENDERPATH_GL11:
9826                 break;
9827         }
9828 }
9829
9830 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9831 {
9832         int i;
9833         const msurface_t *surface;
9834         if (r_waterstate.renderingscene)
9835                 return;
9836         for (i = 0;i < texturenumsurfaces;i++)
9837         {
9838                 surface = texturesurfacelist[i];
9839                 RSurf_BindLightmapForSurface(surface);
9840                 RSurf_BindReflectionForSurface(surface);
9841                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9842                 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);
9843         }
9844 }
9845
9846 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9847 {
9848         int i;
9849         int j;
9850         const msurface_t *surface = texturesurfacelist[0];
9851         const msurface_t *surface2;
9852         int firstvertex;
9853         int endvertex;
9854         int numvertices;
9855         int numtriangles;
9856         if (texturenumsurfaces == 1)
9857         {
9858                 RSurf_BindLightmapForSurface(surface);
9859                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9860                 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);
9861         }
9862         else if (r_batchmode.integer == 2)
9863         {
9864 #define MAXBATCHTRIANGLES 4096
9865                 int batchtriangles = 0;
9866                 static int batchelements[MAXBATCHTRIANGLES*3];
9867                 for (i = 0;i < texturenumsurfaces;i = j)
9868                 {
9869                         surface = texturesurfacelist[i];
9870                         RSurf_BindLightmapForSurface(surface);
9871                         j = i + 1;
9872                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9873                         {
9874                                 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);
9875                                 continue;
9876                         }
9877                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9878                         batchtriangles = surface->num_triangles;
9879                         firstvertex = surface->num_firstvertex;
9880                         endvertex = surface->num_firstvertex + surface->num_vertices;
9881                         for (;j < texturenumsurfaces;j++)
9882                         {
9883                                 surface2 = texturesurfacelist[j];
9884                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9885                                         break;
9886                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9887                                 batchtriangles += surface2->num_triangles;
9888                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9889                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9890                         }
9891                         surface2 = texturesurfacelist[j-1];
9892                         numvertices = endvertex - firstvertex;
9893                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9894                 }
9895         }
9896         else if (r_batchmode.integer == 1)
9897         {
9898 #if 0
9899                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9900                 for (i = 0;i < texturenumsurfaces;i = j)
9901                 {
9902                         surface = texturesurfacelist[i];
9903                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9904                                 if (texturesurfacelist[j] != surface2)
9905                                         break;
9906                         Con_Printf(" %i", j - i);
9907                 }
9908                 Con_Printf("\n");
9909                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9910 #endif
9911                 for (i = 0;i < texturenumsurfaces;i = j)
9912                 {
9913                         surface = texturesurfacelist[i];
9914                         RSurf_BindLightmapForSurface(surface);
9915                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9916                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9917                                         break;
9918 #if 0
9919                         Con_Printf(" %i", j - i);
9920 #endif
9921                         surface2 = texturesurfacelist[j-1];
9922                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9923                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9924                         GL_LockArrays(surface->num_firstvertex, numvertices);
9925                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9926                 }
9927 #if 0
9928                 Con_Printf("\n");
9929 #endif
9930         }
9931         else
9932         {
9933                 for (i = 0;i < texturenumsurfaces;i++)
9934                 {
9935                         surface = texturesurfacelist[i];
9936                         RSurf_BindLightmapForSurface(surface);
9937                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9938                         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);
9939                 }
9940         }
9941 }
9942
9943 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9944 {
9945         int j;
9946         int texturesurfaceindex;
9947         if (r_showsurfaces.integer == 2)
9948         {
9949                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9950                 {
9951                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9952                         for (j = 0;j < surface->num_triangles;j++)
9953                         {
9954                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9955                                 GL_Color(f, f, f, 1);
9956                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9957                         }
9958                 }
9959         }
9960         else
9961         {
9962                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9963                 {
9964                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9965                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9966                         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);
9967                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9968                         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);
9969                 }
9970         }
9971 }
9972
9973 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9974 {
9975         int texturesurfaceindex;
9976         int i;
9977         const float *v;
9978         float *c2;
9979         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9980         {
9981                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9982                 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)
9983                 {
9984                         c2[0] = 0.5;
9985                         c2[1] = 0.5;
9986                         c2[2] = 0.5;
9987                         c2[3] = 1;
9988                 }
9989         }
9990         rsurface.lightmapcolor4f = rsurface.array_color4f;
9991         rsurface.lightmapcolor4f_bufferobject = 0;
9992         rsurface.lightmapcolor4f_bufferoffset = 0;
9993 }
9994
9995 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9996 {
9997         int texturesurfaceindex;
9998         int i;
9999         float f;
10000         const float *v;
10001         const float *c;
10002         float *c2;
10003         if (rsurface.lightmapcolor4f)
10004         {
10005                 // generate color arrays for the surfaces in this list
10006                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10007                 {
10008                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10009                         for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), 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)
10010                         {
10011                                 f = RSurf_FogVertex(v);
10012                                 c2[0] = c[0] * f;
10013                                 c2[1] = c[1] * f;
10014                                 c2[2] = c[2] * f;
10015                                 c2[3] = c[3];
10016                         }
10017                 }
10018         }
10019         else
10020         {
10021                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10022                 {
10023                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10024                         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)
10025                         {
10026                                 f = RSurf_FogVertex(v);
10027                                 c2[0] = f;
10028                                 c2[1] = f;
10029                                 c2[2] = f;
10030                                 c2[3] = 1;
10031                         }
10032                 }
10033         }
10034         rsurface.lightmapcolor4f = rsurface.array_color4f;
10035         rsurface.lightmapcolor4f_bufferobject = 0;
10036         rsurface.lightmapcolor4f_bufferoffset = 0;
10037 }
10038
10039 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10040 {
10041         int texturesurfaceindex;
10042         int i;
10043         float f;
10044         const float *v;
10045         const float *c;
10046         float *c2;
10047         if (!rsurface.lightmapcolor4f)
10048                 return;
10049         // generate color arrays for the surfaces in this list
10050         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10051         {
10052                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10053                 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)
10054                 {
10055                         f = RSurf_FogVertex(v);
10056                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10057                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10058                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10059                         c2[3] = c[3];
10060                 }
10061         }
10062         rsurface.lightmapcolor4f = rsurface.array_color4f;
10063         rsurface.lightmapcolor4f_bufferobject = 0;
10064         rsurface.lightmapcolor4f_bufferoffset = 0;
10065 }
10066
10067 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10068 {
10069         int texturesurfaceindex;
10070         int i;
10071         const float *c;
10072         float *c2;
10073         if (!rsurface.lightmapcolor4f)
10074                 return;
10075         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10076         {
10077                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10078                 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)
10079                 {
10080                         c2[0] = c[0] * r;
10081                         c2[1] = c[1] * g;
10082                         c2[2] = c[2] * b;
10083                         c2[3] = c[3] * a;
10084                 }
10085         }
10086         rsurface.lightmapcolor4f = rsurface.array_color4f;
10087         rsurface.lightmapcolor4f_bufferobject = 0;
10088         rsurface.lightmapcolor4f_bufferoffset = 0;
10089 }
10090
10091 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10092 {
10093         int texturesurfaceindex;
10094         int i;
10095         const float *c;
10096         float *c2;
10097         if (!rsurface.lightmapcolor4f)
10098                 return;
10099         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10100         {
10101                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10102                 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)
10103                 {
10104                         c2[0] = c[0] + r_refdef.scene.ambient;
10105                         c2[1] = c[1] + r_refdef.scene.ambient;
10106                         c2[2] = c[2] + r_refdef.scene.ambient;
10107                         c2[3] = c[3];
10108                 }
10109         }
10110         rsurface.lightmapcolor4f = rsurface.array_color4f;
10111         rsurface.lightmapcolor4f_bufferobject = 0;
10112         rsurface.lightmapcolor4f_bufferoffset = 0;
10113 }
10114
10115 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10116 {
10117         // TODO: optimize
10118         rsurface.lightmapcolor4f = NULL;
10119         rsurface.lightmapcolor4f_bufferobject = 0;
10120         rsurface.lightmapcolor4f_bufferoffset = 0;
10121         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10122         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10123         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10124         GL_Color(r, g, b, a);
10125         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10126 }
10127
10128 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10129 {
10130         // TODO: optimize applyfog && applycolor case
10131         // just apply fog if necessary, and tint the fog color array if necessary
10132         rsurface.lightmapcolor4f = NULL;
10133         rsurface.lightmapcolor4f_bufferobject = 0;
10134         rsurface.lightmapcolor4f_bufferoffset = 0;
10135         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10136         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10137         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10138         GL_Color(r, g, b, a);
10139         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10140 }
10141
10142 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10143 {
10144         int texturesurfaceindex;
10145         int i;
10146         float *c;
10147         // TODO: optimize
10148         if (texturesurfacelist[0]->lightmapinfo)
10149         {
10150                 // generate color arrays for the surfaces in this list
10151                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10152                 {
10153                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10154                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10155                         {
10156                                 if (surface->lightmapinfo->samples)
10157                                 {
10158                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10159                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10160                                         VectorScale(lm, scale, c);
10161                                         if (surface->lightmapinfo->styles[1] != 255)
10162                                         {
10163                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10164                                                 lm += size3;
10165                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10166                                                 VectorMA(c, scale, lm, c);
10167                                                 if (surface->lightmapinfo->styles[2] != 255)
10168                                                 {
10169                                                         lm += size3;
10170                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10171                                                         VectorMA(c, scale, lm, c);
10172                                                         if (surface->lightmapinfo->styles[3] != 255)
10173                                                         {
10174                                                                 lm += size3;
10175                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10176                                                                 VectorMA(c, scale, lm, c);
10177                                                         }
10178                                                 }
10179                                         }
10180                                 }
10181                                 else
10182                                         VectorClear(c);
10183                                 c[3] = 1;
10184                         }
10185                 }
10186                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10187                 rsurface.lightmapcolor4f_bufferobject = 0;
10188                 rsurface.lightmapcolor4f_bufferoffset = 0;
10189         }
10190         else
10191         {
10192                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10193                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10194                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10195         }
10196         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10197         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10198         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10199         GL_Color(r, g, b, a);
10200         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10201 }
10202
10203 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10204 {
10205         int texturesurfaceindex;
10206         int i;
10207         float f;
10208         float alpha;
10209         const float *v;
10210         const float *n;
10211         float *c;
10212         vec3_t ambientcolor;
10213         vec3_t diffusecolor;
10214         vec3_t lightdir;
10215         // TODO: optimize
10216         // model lighting
10217         VectorCopy(rsurface.modellight_lightdir, lightdir);
10218         f = 0.5f * r_refdef.lightmapintensity;
10219         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10220         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10221         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10222         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10223         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10224         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10225         alpha = *a;
10226         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10227         {
10228                 // generate color arrays for the surfaces in this list
10229                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10230                 {
10231                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10232                         int numverts = surface->num_vertices;
10233                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10234                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10235                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10236                         // q3-style directional shading
10237                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10238                         {
10239                                 if ((f = DotProduct(n, lightdir)) > 0)
10240                                         VectorMA(ambientcolor, f, diffusecolor, c);
10241                                 else
10242                                         VectorCopy(ambientcolor, c);
10243                                 c[3] = alpha;
10244                         }
10245                 }
10246                 *r = 1;
10247                 *g = 1;
10248                 *b = 1;
10249                 *a = 1;
10250                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10251                 rsurface.lightmapcolor4f_bufferobject = 0;
10252                 rsurface.lightmapcolor4f_bufferoffset = 0;
10253                 *applycolor = false;
10254         }
10255         else
10256         {
10257                 *r = ambientcolor[0];
10258                 *g = ambientcolor[1];
10259                 *b = ambientcolor[2];
10260                 rsurface.lightmapcolor4f = NULL;
10261                 rsurface.lightmapcolor4f_bufferobject = 0;
10262                 rsurface.lightmapcolor4f_bufferoffset = 0;
10263         }
10264 }
10265
10266 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10267 {
10268         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10269         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10270         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10271         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10272         GL_Color(r, g, b, a);
10273         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10274 }
10275
10276 void RSurf_SetupDepthAndCulling(void)
10277 {
10278         // submodels are biased to avoid z-fighting with world surfaces that they
10279         // may be exactly overlapping (avoids z-fighting artifacts on certain
10280         // doors and things in Quake maps)
10281         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10282         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10283         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10284         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10285 }
10286
10287 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10288 {
10289         // transparent sky would be ridiculous
10290         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10291                 return;
10292         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10293         skyrenderlater = true;
10294         RSurf_SetupDepthAndCulling();
10295         GL_DepthMask(true);
10296         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10297         // skymasking on them, and Quake3 never did sky masking (unlike
10298         // software Quake and software Quake2), so disable the sky masking
10299         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10300         // and skymasking also looks very bad when noclipping outside the
10301         // level, so don't use it then either.
10302         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10303         {
10304                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10305                 R_Mesh_ColorPointer(NULL, 0, 0);
10306                 R_Mesh_ResetTextureState();
10307                 if (skyrendermasked)
10308                 {
10309                         R_SetupShader_DepthOrShadow();
10310                         // depth-only (masking)
10311                         GL_ColorMask(0,0,0,0);
10312                         // just to make sure that braindead drivers don't draw
10313                         // anything despite that colormask...
10314                         GL_BlendFunc(GL_ZERO, GL_ONE);
10315                 }
10316                 else
10317                 {
10318                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10319                         // fog sky
10320                         GL_BlendFunc(GL_ONE, GL_ZERO);
10321                 }
10322                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10323                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10324                 if (skyrendermasked)
10325                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10326         }
10327         R_Mesh_ResetTextureState();
10328         GL_Color(1, 1, 1, 1);
10329 }
10330
10331 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10332 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10333 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10334 {
10335         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10336         if (prepass)
10337         {
10338                 // render screenspace normalmap to texture
10339                 GL_DepthMask(true);
10340                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10341                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10342                 GL_LockArrays(0, 0);
10343         }
10344         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10345         {
10346                 // render water or distortion background, then blend surface on top
10347                 GL_DepthMask(true);
10348                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10349                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10350                 GL_LockArrays(0, 0);
10351                 GL_DepthMask(false);
10352                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10353                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10354                 GL_LockArrays(0, 0);
10355         }
10356         else
10357         {
10358                 // render surface normally
10359                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10360                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10361                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10362                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10363                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10364                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10365                 else
10366                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10367                 GL_LockArrays(0, 0);
10368         }
10369 }
10370
10371 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10372 {
10373         // OpenGL 1.3 path - anything not completely ancient
10374         int texturesurfaceindex;
10375         qboolean applycolor;
10376         qboolean applyfog;
10377         int layerindex;
10378         const texturelayer_t *layer;
10379         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10380
10381         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10382         {
10383                 vec4_t layercolor;
10384                 int layertexrgbscale;
10385                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10386                 {
10387                         if (layerindex == 0)
10388                                 GL_AlphaTest(true);
10389                         else
10390                         {
10391                                 GL_AlphaTest(false);
10392                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10393                         }
10394                 }
10395                 GL_DepthMask(layer->depthmask && writedepth);
10396                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10397                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10398                 {
10399                         layertexrgbscale = 4;
10400                         VectorScale(layer->color, 0.25f, layercolor);
10401                 }
10402                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10403                 {
10404                         layertexrgbscale = 2;
10405                         VectorScale(layer->color, 0.5f, layercolor);
10406                 }
10407                 else
10408                 {
10409                         layertexrgbscale = 1;
10410                         VectorScale(layer->color, 1.0f, layercolor);
10411                 }
10412                 layercolor[3] = layer->color[3];
10413                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10414                 R_Mesh_ColorPointer(NULL, 0, 0);
10415                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10416                 switch (layer->type)
10417                 {
10418                 case TEXTURELAYERTYPE_LITTEXTURE:
10419                         // single-pass lightmapped texture with 2x rgbscale
10420                         R_Mesh_TexBind(0, r_texture_white);
10421                         R_Mesh_TexMatrix(0, NULL);
10422                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10423                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10424                         R_Mesh_TexBind(1, layer->texture);
10425                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10426                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10427                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10428                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10429                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10430                         else if (rsurface.uselightmaptexture)
10431                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10432                         else
10433                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10434                         break;
10435                 case TEXTURELAYERTYPE_TEXTURE:
10436                         // singletexture unlit texture with transparency support
10437                         R_Mesh_TexBind(0, layer->texture);
10438                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10439                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10440                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10441                         R_Mesh_TexBind(1, 0);
10442                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10443                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10444                         break;
10445                 case TEXTURELAYERTYPE_FOG:
10446                         // singletexture fogging
10447                         if (layer->texture)
10448                         {
10449                                 R_Mesh_TexBind(0, layer->texture);
10450                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10451                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10452                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10453                         }
10454                         else
10455                         {
10456                                 R_Mesh_TexBind(0, 0);
10457                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10458                         }
10459                         R_Mesh_TexBind(1, 0);
10460                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10461                         // generate a color array for the fog pass
10462                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10463                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10464                         {
10465                                 int i;
10466                                 float f;
10467                                 const float *v;
10468                                 float *c;
10469                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10470                                 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)
10471                                 {
10472                                         f = 1 - RSurf_FogVertex(v);
10473                                         c[0] = layercolor[0];
10474                                         c[1] = layercolor[1];
10475                                         c[2] = layercolor[2];
10476                                         c[3] = f * layercolor[3];
10477                                 }
10478                         }
10479                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10480                         break;
10481                 default:
10482                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10483                 }
10484                 GL_LockArrays(0, 0);
10485         }
10486         CHECKGLERROR
10487         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10488         {
10489                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10490                 GL_AlphaTest(false);
10491         }
10492 }
10493
10494 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10495 {
10496         // OpenGL 1.1 - crusty old voodoo path
10497         int texturesurfaceindex;
10498         qboolean applyfog;
10499         int layerindex;
10500         const texturelayer_t *layer;
10501         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10502
10503         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10504         {
10505                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10506                 {
10507                         if (layerindex == 0)
10508                                 GL_AlphaTest(true);
10509                         else
10510                         {
10511                                 GL_AlphaTest(false);
10512                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10513                         }
10514                 }
10515                 GL_DepthMask(layer->depthmask && writedepth);
10516                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10517                 R_Mesh_ColorPointer(NULL, 0, 0);
10518                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10519                 switch (layer->type)
10520                 {
10521                 case TEXTURELAYERTYPE_LITTEXTURE:
10522                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10523                         {
10524                                 // two-pass lit texture with 2x rgbscale
10525                                 // first the lightmap pass
10526                                 R_Mesh_TexBind(0, r_texture_white);
10527                                 R_Mesh_TexMatrix(0, NULL);
10528                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10529                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10530                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10531                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10532                                 else if (rsurface.uselightmaptexture)
10533                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10534                                 else
10535                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10536                                 GL_LockArrays(0, 0);
10537                                 // then apply the texture to it
10538                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10539                                 R_Mesh_TexBind(0, layer->texture);
10540                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10541                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10542                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10543                                 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 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);
10544                         }
10545                         else
10546                         {
10547                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10548                                 R_Mesh_TexBind(0, layer->texture);
10549                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10550                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10551                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10552                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10553                                         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);
10554                                 else
10555                                         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);
10556                         }
10557                         break;
10558                 case TEXTURELAYERTYPE_TEXTURE:
10559                         // singletexture unlit texture with transparency support
10560                         R_Mesh_TexBind(0, layer->texture);
10561                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10562                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10563                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10564                         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);
10565                         break;
10566                 case TEXTURELAYERTYPE_FOG:
10567                         // singletexture fogging
10568                         if (layer->texture)
10569                         {
10570                                 R_Mesh_TexBind(0, layer->texture);
10571                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10572                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10573                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10574                         }
10575                         else
10576                         {
10577                                 R_Mesh_TexBind(0, 0);
10578                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10579                         }
10580                         // generate a color array for the fog pass
10581                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10582                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10583                         {
10584                                 int i;
10585                                 float f;
10586                                 const float *v;
10587                                 float *c;
10588                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10589                                 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)
10590                                 {
10591                                         f = 1 - RSurf_FogVertex(v);
10592                                         c[0] = layer->color[0];
10593                                         c[1] = layer->color[1];
10594                                         c[2] = layer->color[2];
10595                                         c[3] = f * layer->color[3];
10596                                 }
10597                         }
10598                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10599                         break;
10600                 default:
10601                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10602                 }
10603                 GL_LockArrays(0, 0);
10604         }
10605         CHECKGLERROR
10606         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10607         {
10608                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10609                 GL_AlphaTest(false);
10610         }
10611 }
10612
10613 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10614 {
10615         float c[4];
10616
10617         GL_AlphaTest(false);
10618         R_Mesh_ColorPointer(NULL, 0, 0);
10619         R_Mesh_ResetTextureState();
10620         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10621
10622         if(rsurface.texture && rsurface.texture->currentskinframe)
10623         {
10624                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10625                 c[3] *= rsurface.texture->currentalpha;
10626         }
10627         else
10628         {
10629                 c[0] = 1;
10630                 c[1] = 0;
10631                 c[2] = 1;
10632                 c[3] = 1;
10633         }
10634
10635         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10636         {
10637                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10638                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10639                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10640         }
10641
10642         // brighten it up (as texture value 127 means "unlit")
10643         c[0] *= 2 * r_refdef.view.colorscale;
10644         c[1] *= 2 * r_refdef.view.colorscale;
10645         c[2] *= 2 * r_refdef.view.colorscale;
10646
10647         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10648                 c[3] *= r_wateralpha.value;
10649
10650         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10651         {
10652                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10653                 GL_DepthMask(false);
10654         }
10655         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10656         {
10657                 GL_BlendFunc(GL_ONE, GL_ONE);
10658                 GL_DepthMask(false);
10659         }
10660         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10661         {
10662                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10663                 GL_DepthMask(false);
10664         }
10665         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10666         {
10667                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10668                 GL_DepthMask(false);
10669         }
10670         else
10671         {
10672                 GL_BlendFunc(GL_ONE, GL_ZERO);
10673                 GL_DepthMask(writedepth);
10674         }
10675
10676         rsurface.lightmapcolor4f = NULL;
10677
10678         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10679         {
10680                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10681
10682                 rsurface.lightmapcolor4f = NULL;
10683                 rsurface.lightmapcolor4f_bufferobject = 0;
10684                 rsurface.lightmapcolor4f_bufferoffset = 0;
10685         }
10686         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10687         {
10688                 qboolean applycolor = true;
10689                 float one = 1.0;
10690
10691                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10692
10693                 r_refdef.lightmapintensity = 1;
10694                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10695                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10696         }
10697         else
10698         {
10699                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10700
10701                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10702                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10703                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10704         }
10705
10706         if(!rsurface.lightmapcolor4f)
10707                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10708
10709         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10710         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10711         if(r_refdef.fogenabled)
10712                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10713
10714         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10715         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10716 }
10717
10718 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10719 {
10720         CHECKGLERROR
10721         RSurf_SetupDepthAndCulling();
10722         if (r_showsurfaces.integer == 3 && !prepass)
10723         {
10724                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10725                 return;
10726         }
10727         switch (vid.renderpath)
10728         {
10729         case RENDERPATH_GL20:
10730         case RENDERPATH_CGGL:
10731                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10732                 break;
10733         case RENDERPATH_GL13:
10734                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10735                 break;
10736         case RENDERPATH_GL11:
10737                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10738                 break;
10739         }
10740         CHECKGLERROR
10741 }
10742
10743 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10744 {
10745         CHECKGLERROR
10746         RSurf_SetupDepthAndCulling();
10747         if (r_showsurfaces.integer == 3 && !prepass)
10748         {
10749                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10750                 return;
10751         }
10752         switch (vid.renderpath)
10753         {
10754         case RENDERPATH_GL20:
10755         case RENDERPATH_CGGL:
10756                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10757                 break;
10758         case RENDERPATH_GL13:
10759                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10760                 break;
10761         case RENDERPATH_GL11:
10762                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10763                 break;
10764         }
10765         CHECKGLERROR
10766 }
10767
10768 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10769 {
10770         int i, j;
10771         int texturenumsurfaces, endsurface;
10772         texture_t *texture;
10773         const msurface_t *surface;
10774         const msurface_t *texturesurfacelist[256];
10775
10776         // if the model is static it doesn't matter what value we give for
10777         // wantnormals and wanttangents, so this logic uses only rules applicable
10778         // to a model, knowing that they are meaningless otherwise
10779         if (ent == r_refdef.scene.worldentity)
10780                 RSurf_ActiveWorldEntity();
10781         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10782                 RSurf_ActiveModelEntity(ent, false, false, false);
10783         else
10784         {
10785                 switch (vid.renderpath)
10786                 {
10787                 case RENDERPATH_GL20:
10788                 case RENDERPATH_CGGL:
10789                         RSurf_ActiveModelEntity(ent, true, true, false);
10790                         break;
10791                 case RENDERPATH_GL13:
10792                 case RENDERPATH_GL11:
10793                         RSurf_ActiveModelEntity(ent, true, false, false);
10794                         break;
10795                 }
10796         }
10797
10798         if (r_transparentdepthmasking.integer)
10799         {
10800                 qboolean setup = false;
10801                 for (i = 0;i < numsurfaces;i = j)
10802                 {
10803                         j = i + 1;
10804                         surface = rsurface.modelsurfaces + surfacelist[i];
10805                         texture = surface->texture;
10806                         rsurface.texture = R_GetCurrentTexture(texture);
10807                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10808                         // scan ahead until we find a different texture
10809                         endsurface = min(i + 1024, numsurfaces);
10810                         texturenumsurfaces = 0;
10811                         texturesurfacelist[texturenumsurfaces++] = surface;
10812                         for (;j < endsurface;j++)
10813                         {
10814                                 surface = rsurface.modelsurfaces + surfacelist[j];
10815                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10816                                         break;
10817                                 texturesurfacelist[texturenumsurfaces++] = surface;
10818                         }
10819                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10820                                 continue;
10821                         // render the range of surfaces as depth
10822                         if (!setup)
10823                         {
10824                                 setup = true;
10825                                 GL_ColorMask(0,0,0,0);
10826                                 GL_Color(1,1,1,1);
10827                                 GL_DepthTest(true);
10828                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10829                                 GL_DepthMask(true);
10830                                 GL_AlphaTest(false);
10831                                 R_Mesh_ColorPointer(NULL, 0, 0);
10832                                 R_Mesh_ResetTextureState();
10833                                 R_SetupShader_DepthOrShadow();
10834                         }
10835                         RSurf_SetupDepthAndCulling();
10836                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10837                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10838                 }
10839                 if (setup)
10840                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10841         }
10842
10843         for (i = 0;i < numsurfaces;i = j)
10844         {
10845                 j = i + 1;
10846                 surface = rsurface.modelsurfaces + surfacelist[i];
10847                 texture = surface->texture;
10848                 rsurface.texture = R_GetCurrentTexture(texture);
10849                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10850                 // scan ahead until we find a different texture
10851                 endsurface = min(i + 1024, numsurfaces);
10852                 texturenumsurfaces = 0;
10853                 texturesurfacelist[texturenumsurfaces++] = surface;
10854                 for (;j < endsurface;j++)
10855                 {
10856                         surface = rsurface.modelsurfaces + surfacelist[j];
10857                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10858                                 break;
10859                         texturesurfacelist[texturenumsurfaces++] = surface;
10860                 }
10861                 // render the range of surfaces
10862                 if (ent == r_refdef.scene.worldentity)
10863                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10864                 else
10865                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10866         }
10867         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10868         GL_AlphaTest(false);
10869 }
10870
10871 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10872 {
10873         // transparent surfaces get pushed off into the transparent queue
10874         int surfacelistindex;
10875         const msurface_t *surface;
10876         vec3_t tempcenter, center;
10877         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10878         {
10879                 surface = texturesurfacelist[surfacelistindex];
10880                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10881                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10882                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10883                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10884                 if (queueentity->transparent_offset) // transparent offset
10885                 {
10886                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10887                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10888                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10889                 }
10890                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10891         }
10892 }
10893
10894 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10895 {
10896         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10897         CHECKGLERROR
10898         if (depthonly)
10899         {
10900                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10901                         return;
10902                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10903                         return;
10904                 RSurf_SetupDepthAndCulling();
10905                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10906                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10907         }
10908         else if (prepass)
10909         {
10910                 if (!rsurface.texture->currentnumlayers)
10911                         return;
10912                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10913                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10914                 else
10915                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10916         }
10917         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10918         {
10919                 RSurf_SetupDepthAndCulling();
10920                 GL_AlphaTest(false);
10921                 R_Mesh_ColorPointer(NULL, 0, 0);
10922                 R_Mesh_ResetTextureState();
10923                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10924                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10925                 GL_DepthMask(true);
10926                 GL_BlendFunc(GL_ONE, GL_ZERO);
10927                 GL_Color(0, 0, 0, 1);
10928                 GL_DepthTest(writedepth);
10929                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10930         }
10931         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10932         {
10933                 RSurf_SetupDepthAndCulling();
10934                 GL_AlphaTest(false);
10935                 R_Mesh_ColorPointer(NULL, 0, 0);
10936                 R_Mesh_ResetTextureState();
10937                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10938                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10939                 GL_DepthMask(true);
10940                 GL_BlendFunc(GL_ONE, GL_ZERO);
10941                 GL_DepthTest(true);
10942                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10943         }
10944         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10945                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10946         else if (!rsurface.texture->currentnumlayers)
10947                 return;
10948         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10949         {
10950                 // in the deferred case, transparent surfaces were queued during prepass
10951                 if (!r_shadow_usingdeferredprepass)
10952                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10953         }
10954         else
10955         {
10956                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10957                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10958         }
10959         CHECKGLERROR
10960 }
10961
10962 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10963 {
10964         int i, j;
10965         texture_t *texture;
10966         // break the surface list down into batches by texture and use of lightmapping
10967         for (i = 0;i < numsurfaces;i = j)
10968         {
10969                 j = i + 1;
10970                 // texture is the base texture pointer, rsurface.texture is the
10971                 // current frame/skin the texture is directing us to use (for example
10972                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10973                 // use skin 1 instead)
10974                 texture = surfacelist[i]->texture;
10975                 rsurface.texture = R_GetCurrentTexture(texture);
10976                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10977                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10978                 {
10979                         // if this texture is not the kind we want, skip ahead to the next one
10980                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10981                                 ;
10982                         continue;
10983                 }
10984                 // simply scan ahead until we find a different texture or lightmap state
10985                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10986                         ;
10987                 // render the range of surfaces
10988                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10989         }
10990 }
10991
10992 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10993 {
10994         CHECKGLERROR
10995         if (depthonly)
10996         {
10997                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10998                         return;
10999                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11000                         return;
11001                 RSurf_SetupDepthAndCulling();
11002                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11003                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11004         }
11005         else if (prepass)
11006         {
11007                 if (!rsurface.texture->currentnumlayers)
11008                         return;
11009                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11010                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11011                 else
11012                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11013         }
11014         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11015         {
11016                 RSurf_SetupDepthAndCulling();
11017                 GL_AlphaTest(false);
11018                 R_Mesh_ColorPointer(NULL, 0, 0);
11019                 R_Mesh_ResetTextureState();
11020                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11021                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11022                 GL_DepthMask(true);
11023                 GL_BlendFunc(GL_ONE, GL_ZERO);
11024                 GL_Color(0, 0, 0, 1);
11025                 GL_DepthTest(writedepth);
11026                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11027         }
11028         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11029         {
11030                 RSurf_SetupDepthAndCulling();
11031                 GL_AlphaTest(false);
11032                 R_Mesh_ColorPointer(NULL, 0, 0);
11033                 R_Mesh_ResetTextureState();
11034                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11035                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11036                 GL_DepthMask(true);
11037                 GL_BlendFunc(GL_ONE, GL_ZERO);
11038                 GL_DepthTest(true);
11039                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11040         }
11041         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11042                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11043         else if (!rsurface.texture->currentnumlayers)
11044                 return;
11045         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11046         {
11047                 // in the deferred case, transparent surfaces were queued during prepass
11048                 if (!r_shadow_usingdeferredprepass)
11049                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11050         }
11051         else
11052         {
11053                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11054                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11055         }
11056         CHECKGLERROR
11057 }
11058
11059 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11060 {
11061         int i, j;
11062         texture_t *texture;
11063         // break the surface list down into batches by texture and use of lightmapping
11064         for (i = 0;i < numsurfaces;i = j)
11065         {
11066                 j = i + 1;
11067                 // texture is the base texture pointer, rsurface.texture is the
11068                 // current frame/skin the texture is directing us to use (for example
11069                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11070                 // use skin 1 instead)
11071                 texture = surfacelist[i]->texture;
11072                 rsurface.texture = R_GetCurrentTexture(texture);
11073                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11074                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11075                 {
11076                         // if this texture is not the kind we want, skip ahead to the next one
11077                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11078                                 ;
11079                         continue;
11080                 }
11081                 // simply scan ahead until we find a different texture or lightmap state
11082                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11083                         ;
11084                 // render the range of surfaces
11085                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11086         }
11087 }
11088
11089 float locboxvertex3f[6*4*3] =
11090 {
11091         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11092         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11093         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11094         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11095         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11096         1,0,0, 0,0,0, 0,1,0, 1,1,0
11097 };
11098
11099 unsigned short locboxelements[6*2*3] =
11100 {
11101          0, 1, 2, 0, 2, 3,
11102          4, 5, 6, 4, 6, 7,
11103          8, 9,10, 8,10,11,
11104         12,13,14, 12,14,15,
11105         16,17,18, 16,18,19,
11106         20,21,22, 20,22,23
11107 };
11108
11109 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11110 {
11111         int i, j;
11112         cl_locnode_t *loc = (cl_locnode_t *)ent;
11113         vec3_t mins, size;
11114         float vertex3f[6*4*3];
11115         CHECKGLERROR
11116         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11117         GL_DepthMask(false);
11118         GL_DepthRange(0, 1);
11119         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11120         GL_DepthTest(true);
11121         GL_CullFace(GL_NONE);
11122         R_EntityMatrix(&identitymatrix);
11123
11124         R_Mesh_VertexPointer(vertex3f, 0, 0);
11125         R_Mesh_ColorPointer(NULL, 0, 0);
11126         R_Mesh_ResetTextureState();
11127         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11128
11129         i = surfacelist[0];
11130         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11131                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11132                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11133                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11134
11135         if (VectorCompare(loc->mins, loc->maxs))
11136         {
11137                 VectorSet(size, 2, 2, 2);
11138                 VectorMA(loc->mins, -0.5f, size, mins);
11139         }
11140         else
11141         {
11142                 VectorCopy(loc->mins, mins);
11143                 VectorSubtract(loc->maxs, loc->mins, size);
11144         }
11145
11146         for (i = 0;i < 6*4*3;)
11147                 for (j = 0;j < 3;j++, i++)
11148                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11149
11150         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11151 }
11152
11153 void R_DrawLocs(void)
11154 {
11155         int index;
11156         cl_locnode_t *loc, *nearestloc;
11157         vec3_t center;
11158         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11159         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11160         {
11161                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11162                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11163         }
11164 }
11165
11166 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11167 {
11168         if (decalsystem->decals)
11169                 Mem_Free(decalsystem->decals);
11170         memset(decalsystem, 0, sizeof(*decalsystem));
11171 }
11172
11173 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)
11174 {
11175         tridecal_t *decal;
11176         tridecal_t *decals;
11177         int i;
11178         int maxdecals;
11179
11180         // expand or initialize the system
11181         if (decalsystem->maxdecals <= decalsystem->numdecals)
11182         {
11183                 decalsystem_t old = *decalsystem;
11184                 qboolean useshortelements;
11185                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11186                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11187                 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)));
11188                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11189                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11190                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11191                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11192                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11193                 if (decalsystem->numdecals)
11194                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11195                 if (old.decals)
11196                         Mem_Free(old.decals);
11197                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11198                         decalsystem->element3i[i] = i;
11199                 if (useshortelements)
11200                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11201                                 decalsystem->element3s[i] = i;
11202         }
11203
11204         // grab a decal and search for another free slot for the next one
11205         maxdecals = decalsystem->maxdecals;
11206         decals = decalsystem->decals;
11207         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11208         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11209                 ;
11210         decalsystem->freedecal = i;
11211         if (decalsystem->numdecals <= i)
11212                 decalsystem->numdecals = i + 1;
11213
11214         // initialize the decal
11215         decal->lived = 0;
11216         decal->triangleindex = triangleindex;
11217         decal->surfaceindex = surfaceindex;
11218         decal->decalsequence = decalsequence;
11219         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11220         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11221         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11222         decal->color4ub[0][3] = 255;
11223         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11224         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11225         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11226         decal->color4ub[1][3] = 255;
11227         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11228         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11229         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11230         decal->color4ub[2][3] = 255;
11231         decal->vertex3f[0][0] = v0[0];
11232         decal->vertex3f[0][1] = v0[1];
11233         decal->vertex3f[0][2] = v0[2];
11234         decal->vertex3f[1][0] = v1[0];
11235         decal->vertex3f[1][1] = v1[1];
11236         decal->vertex3f[1][2] = v1[2];
11237         decal->vertex3f[2][0] = v2[0];
11238         decal->vertex3f[2][1] = v2[1];
11239         decal->vertex3f[2][2] = v2[2];
11240         decal->texcoord2f[0][0] = t0[0];
11241         decal->texcoord2f[0][1] = t0[1];
11242         decal->texcoord2f[1][0] = t1[0];
11243         decal->texcoord2f[1][1] = t1[1];
11244         decal->texcoord2f[2][0] = t2[0];
11245         decal->texcoord2f[2][1] = t2[1];
11246 }
11247
11248 extern cvar_t cl_decals_bias;
11249 extern cvar_t cl_decals_models;
11250 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11251 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)
11252 {
11253         matrix4x4_t projection;
11254         decalsystem_t *decalsystem;
11255         qboolean dynamic;
11256         dp_model_t *model;
11257         const float *vertex3f;
11258         const msurface_t *surface;
11259         const msurface_t *surfaces;
11260         const int *surfacelist;
11261         const texture_t *texture;
11262         int numvertices;
11263         int numtriangles;
11264         int numsurfacelist;
11265         int surfacelistindex;
11266         int surfaceindex;
11267         int triangleindex;
11268         int decalsurfaceindex;
11269         int cornerindex;
11270         int index;
11271         int numpoints;
11272         const int *e;
11273         float localorigin[3];
11274         float localnormal[3];
11275         float localmins[3];
11276         float localmaxs[3];
11277         float localsize;
11278         float ilocalsize;
11279         float v[9][3];
11280         float tc[9][2];
11281         float c[9][4];
11282         //float normal[3];
11283         float planes[6][4];
11284         float f;
11285         float points[2][9][3];
11286         float angles[3];
11287         float temp[3];
11288
11289         decalsystem = &ent->decalsystem;
11290         model = ent->model;
11291         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11292         {
11293                 R_DecalSystem_Reset(&ent->decalsystem);
11294                 return;
11295         }
11296
11297         if (!model->brush.data_nodes && !cl_decals_models.integer)
11298         {
11299                 if (decalsystem->model)
11300                         R_DecalSystem_Reset(decalsystem);
11301                 return;
11302         }
11303
11304         if (decalsystem->model != model)
11305                 R_DecalSystem_Reset(decalsystem);
11306         decalsystem->model = model;
11307
11308         RSurf_ActiveModelEntity(ent, false, false, false);
11309
11310         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11311         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11312         VectorNormalize(localnormal);
11313         localsize = worldsize*rsurface.inversematrixscale;
11314         ilocalsize = 1.0f / localsize;
11315         localmins[0] = localorigin[0] - localsize;
11316         localmins[1] = localorigin[1] - localsize;
11317         localmins[2] = localorigin[2] - localsize;
11318         localmaxs[0] = localorigin[0] + localsize;
11319         localmaxs[1] = localorigin[1] + localsize;
11320         localmaxs[2] = localorigin[2] + localsize;
11321
11322         //VectorCopy(localnormal, planes[4]);
11323         //VectorVectors(planes[4], planes[2], planes[0]);
11324         AnglesFromVectors(angles, localnormal, NULL, false);
11325         AngleVectors(angles, planes[0], planes[2], planes[4]);
11326         VectorNegate(planes[0], planes[1]);
11327         VectorNegate(planes[2], planes[3]);
11328         VectorNegate(planes[4], planes[5]);
11329         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11330         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11331         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11332         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11333         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11334         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11335
11336 #if 1
11337 // works
11338 {
11339         matrix4x4_t forwardprojection;
11340         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11341         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11342 }
11343 #else
11344 // broken
11345 {
11346         float projectionvector[4][3];
11347         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11348         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11349         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11350         projectionvector[0][0] = planes[0][0] * ilocalsize;
11351         projectionvector[0][1] = planes[1][0] * ilocalsize;
11352         projectionvector[0][2] = planes[2][0] * ilocalsize;
11353         projectionvector[1][0] = planes[0][1] * ilocalsize;
11354         projectionvector[1][1] = planes[1][1] * ilocalsize;
11355         projectionvector[1][2] = planes[2][1] * ilocalsize;
11356         projectionvector[2][0] = planes[0][2] * ilocalsize;
11357         projectionvector[2][1] = planes[1][2] * ilocalsize;
11358         projectionvector[2][2] = planes[2][2] * ilocalsize;
11359         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11360         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11361         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11362         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11363 }
11364 #endif
11365
11366         dynamic = model->surfmesh.isanimated;
11367         vertex3f = rsurface.modelvertex3f;
11368         numsurfacelist = model->nummodelsurfaces;
11369         surfacelist = model->sortedmodelsurfaces;
11370         surfaces = model->data_surfaces;
11371         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11372         {
11373                 surfaceindex = surfacelist[surfacelistindex];
11374                 surface = surfaces + surfaceindex;
11375                 // skip transparent surfaces
11376                 texture = surface->texture;
11377                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11378                         continue;
11379                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11380                         continue;
11381                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11382                         continue;
11383                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11384                 numvertices = surface->num_vertices;
11385                 numtriangles = surface->num_triangles;
11386                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11387                 {
11388                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11389                         {
11390                                 index = 3*e[cornerindex];
11391                                 VectorCopy(vertex3f + index, v[cornerindex]);
11392                         }
11393                         // cull backfaces
11394                         //TriangleNormal(v[0], v[1], v[2], normal);
11395                         //if (DotProduct(normal, localnormal) < 0.0f)
11396                         //      continue;
11397                         // clip by each of the box planes formed from the projection matrix
11398                         // if anything survives, we emit the decal
11399                         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]);
11400                         if (numpoints < 3)
11401                                 continue;
11402                         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]);
11403                         if (numpoints < 3)
11404                                 continue;
11405                         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]);
11406                         if (numpoints < 3)
11407                                 continue;
11408                         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]);
11409                         if (numpoints < 3)
11410                                 continue;
11411                         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]);
11412                         if (numpoints < 3)
11413                                 continue;
11414                         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]);
11415                         if (numpoints < 3)
11416                                 continue;
11417                         // some part of the triangle survived, so we have to accept it...
11418                         if (dynamic)
11419                         {
11420                                 // dynamic always uses the original triangle
11421                                 numpoints = 3;
11422                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11423                                 {
11424                                         index = 3*e[cornerindex];
11425                                         VectorCopy(vertex3f + index, v[cornerindex]);
11426                                 }
11427                         }
11428                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11429                         {
11430                                 // convert vertex positions to texcoords
11431                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11432                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11433                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11434                                 // calculate distance fade from the projection origin
11435                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11436                                 f = bound(0.0f, f, 1.0f);
11437                                 c[cornerindex][0] = r * f;
11438                                 c[cornerindex][1] = g * f;
11439                                 c[cornerindex][2] = b * f;
11440                                 c[cornerindex][3] = 1.0f;
11441                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11442                         }
11443                         if (dynamic)
11444                                 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);
11445                         else
11446                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11447                                         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);
11448                 }
11449         }
11450 }
11451
11452 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11453 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)
11454 {
11455         int renderentityindex;
11456         float worldmins[3];
11457         float worldmaxs[3];
11458         entity_render_t *ent;
11459
11460         if (!cl_decals_newsystem.integer)
11461                 return;
11462
11463         worldmins[0] = worldorigin[0] - worldsize;
11464         worldmins[1] = worldorigin[1] - worldsize;
11465         worldmins[2] = worldorigin[2] - worldsize;
11466         worldmaxs[0] = worldorigin[0] + worldsize;
11467         worldmaxs[1] = worldorigin[1] + worldsize;
11468         worldmaxs[2] = worldorigin[2] + worldsize;
11469
11470         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11471
11472         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11473         {
11474                 ent = r_refdef.scene.entities[renderentityindex];
11475                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11476                         continue;
11477
11478                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11479         }
11480 }
11481
11482 typedef struct r_decalsystem_splatqueue_s
11483 {
11484         vec3_t worldorigin;
11485         vec3_t worldnormal;
11486         float color[4];
11487         float tcrange[4];
11488         float worldsize;
11489         int decalsequence;
11490 }
11491 r_decalsystem_splatqueue_t;
11492
11493 int r_decalsystem_numqueued = 0;
11494 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11495
11496 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)
11497 {
11498         r_decalsystem_splatqueue_t *queue;
11499
11500         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11501                 return;
11502
11503         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11504         VectorCopy(worldorigin, queue->worldorigin);
11505         VectorCopy(worldnormal, queue->worldnormal);
11506         Vector4Set(queue->color, r, g, b, a);
11507         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11508         queue->worldsize = worldsize;
11509         queue->decalsequence = cl.decalsequence++;
11510 }
11511
11512 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11513 {
11514         int i;
11515         r_decalsystem_splatqueue_t *queue;
11516
11517         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11518                 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);
11519         r_decalsystem_numqueued = 0;
11520 }
11521
11522 extern cvar_t cl_decals_max;
11523 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11524 {
11525         int i;
11526         decalsystem_t *decalsystem = &ent->decalsystem;
11527         int numdecals;
11528         int killsequence;
11529         tridecal_t *decal;
11530         float frametime;
11531         float lifetime;
11532
11533         if (!decalsystem->numdecals)
11534                 return;
11535
11536         if (r_showsurfaces.integer)
11537                 return;
11538
11539         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11540         {
11541                 R_DecalSystem_Reset(decalsystem);
11542                 return;
11543         }
11544
11545         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11546         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11547
11548         if (decalsystem->lastupdatetime)
11549                 frametime = (cl.time - decalsystem->lastupdatetime);
11550         else
11551                 frametime = 0;
11552         decalsystem->lastupdatetime = cl.time;
11553         decal = decalsystem->decals;
11554         numdecals = decalsystem->numdecals;
11555
11556         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11557         {
11558                 if (decal->color4ub[0][3])
11559                 {
11560                         decal->lived += frametime;
11561                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11562                         {
11563                                 memset(decal, 0, sizeof(*decal));
11564                                 if (decalsystem->freedecal > i)
11565                                         decalsystem->freedecal = i;
11566                         }
11567                 }
11568         }
11569         decal = decalsystem->decals;
11570         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11571                 numdecals--;
11572
11573         // collapse the array by shuffling the tail decals into the gaps
11574         for (;;)
11575         {
11576                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11577                         decalsystem->freedecal++;
11578                 if (decalsystem->freedecal == numdecals)
11579                         break;
11580                 decal[decalsystem->freedecal] = decal[--numdecals];
11581         }
11582
11583         decalsystem->numdecals = numdecals;
11584
11585         if (numdecals <= 0)
11586         {
11587                 // if there are no decals left, reset decalsystem
11588                 R_DecalSystem_Reset(decalsystem);
11589         }
11590 }
11591
11592 extern skinframe_t *decalskinframe;
11593 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11594 {
11595         int i;
11596         decalsystem_t *decalsystem = &ent->decalsystem;
11597         int numdecals;
11598         tridecal_t *decal;
11599         float fadedelay;
11600         float faderate;
11601         float alpha;
11602         float *v3f;
11603         float *c4f;
11604         float *t2f;
11605         const int *e;
11606         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11607         int numtris = 0;
11608
11609         numdecals = decalsystem->numdecals;
11610         if (!numdecals)
11611                 return;
11612
11613         if (r_showsurfaces.integer)
11614                 return;
11615
11616         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11617         {
11618                 R_DecalSystem_Reset(decalsystem);
11619                 return;
11620         }
11621
11622         // if the model is static it doesn't matter what value we give for
11623         // wantnormals and wanttangents, so this logic uses only rules applicable
11624         // to a model, knowing that they are meaningless otherwise
11625         if (ent == r_refdef.scene.worldentity)
11626                 RSurf_ActiveWorldEntity();
11627         else
11628                 RSurf_ActiveModelEntity(ent, false, false, false);
11629
11630         decalsystem->lastupdatetime = cl.time;
11631         decal = decalsystem->decals;
11632
11633         fadedelay = cl_decals_time.value;
11634         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11635
11636         // update vertex positions for animated models
11637         v3f = decalsystem->vertex3f;
11638         c4f = decalsystem->color4f;
11639         t2f = decalsystem->texcoord2f;
11640         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11641         {
11642                 if (!decal->color4ub[0][3])
11643                         continue;
11644
11645                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11646                         continue;
11647
11648                 // update color values for fading decals
11649                 if (decal->lived >= cl_decals_time.value)
11650                 {
11651                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11652                         alpha *= (1.0f/255.0f);
11653                 }
11654                 else
11655                         alpha = 1.0f/255.0f;
11656
11657                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11658                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11659                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11660                 c4f[ 3] = 1;
11661                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11662                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11663                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11664                 c4f[ 7] = 1;
11665                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11666                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11667                 c4f[10] = decal->color4ub[2][2] * alpha;
11668                 c4f[11] = 1;
11669
11670                 t2f[0] = decal->texcoord2f[0][0];
11671                 t2f[1] = decal->texcoord2f[0][1];
11672                 t2f[2] = decal->texcoord2f[1][0];
11673                 t2f[3] = decal->texcoord2f[1][1];
11674                 t2f[4] = decal->texcoord2f[2][0];
11675                 t2f[5] = decal->texcoord2f[2][1];
11676
11677                 // update vertex positions for animated models
11678                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11679                 {
11680                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11681                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11682                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11683                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11684                 }
11685                 else
11686                 {
11687                         VectorCopy(decal->vertex3f[0], v3f);
11688                         VectorCopy(decal->vertex3f[1], v3f + 3);
11689                         VectorCopy(decal->vertex3f[2], v3f + 6);
11690                 }
11691
11692                 v3f += 9;
11693                 c4f += 12;
11694                 t2f += 6;
11695                 numtris++;
11696         }
11697
11698         if (numtris > 0)
11699         {
11700                 r_refdef.stats.drawndecals += numtris;
11701
11702                 if (r_refdef.fogenabled)
11703                 {
11704                         switch(vid.renderpath)
11705                         {
11706                         case RENDERPATH_GL20:
11707                         case RENDERPATH_CGGL:
11708                         case RENDERPATH_GL13:
11709                         case RENDERPATH_GL11:
11710                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11711                                 {
11712                                         alpha = RSurf_FogVertex(v3f);
11713                                         c4f[0] *= alpha;
11714                                         c4f[1] *= alpha;
11715                                         c4f[2] *= alpha;
11716                                 }
11717                                 break;
11718                         }
11719                 }
11720
11721                 // now render the decals all at once
11722                 // (this assumes they all use one particle font texture!)
11723                 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);
11724                 R_Mesh_ResetTextureState();
11725                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11726                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11727                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11728                 GL_DepthMask(false);
11729                 GL_DepthRange(0, 1);
11730                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11731                 GL_DepthTest(true);
11732                 GL_CullFace(GL_NONE);
11733                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11734                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11735                 GL_LockArrays(0, numtris * 3);
11736                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11737                 GL_LockArrays(0, 0);
11738         }
11739 }
11740
11741 static void R_DrawModelDecals(void)
11742 {
11743         int i, numdecals;
11744
11745         // fade faster when there are too many decals
11746         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11747         for (i = 0;i < r_refdef.scene.numentities;i++)
11748                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11749
11750         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11751         for (i = 0;i < r_refdef.scene.numentities;i++)
11752                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11753                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11754
11755         R_DecalSystem_ApplySplatEntitiesQueue();
11756
11757         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11758         for (i = 0;i < r_refdef.scene.numentities;i++)
11759                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11760
11761         r_refdef.stats.totaldecals += numdecals;
11762
11763         if (r_showsurfaces.integer)
11764                 return;
11765
11766         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11767
11768         for (i = 0;i < r_refdef.scene.numentities;i++)
11769         {
11770                 if (!r_refdef.viewcache.entityvisible[i])
11771                         continue;
11772                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11773                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11774         }
11775 }
11776
11777 void R_DrawDebugModel(void)
11778 {
11779         entity_render_t *ent = rsurface.entity;
11780         int i, j, k, l, flagsmask;
11781         const int *elements;
11782         q3mbrush_t *brush;
11783         const msurface_t *surface;
11784         dp_model_t *model = ent->model;
11785         vec3_t v;
11786
11787         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11788
11789         R_Mesh_ColorPointer(NULL, 0, 0);
11790         R_Mesh_ResetTextureState();
11791         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11792         GL_DepthRange(0, 1);
11793         GL_DepthTest(!r_showdisabledepthtest.integer);
11794         GL_DepthMask(false);
11795         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11796
11797         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11798         {
11799                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11800                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11801                 {
11802                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11803                         {
11804                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11805                                 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);
11806                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11807                         }
11808                 }
11809                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11810                 {
11811                         if (surface->num_collisiontriangles)
11812                         {
11813                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11814                                 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);
11815                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11816                         }
11817                 }
11818         }
11819
11820         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11821
11822         if (r_showtris.integer || r_shownormals.integer)
11823         {
11824                 if (r_showdisabledepthtest.integer)
11825                 {
11826                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11827                         GL_DepthMask(false);
11828                 }
11829                 else
11830                 {
11831                         GL_BlendFunc(GL_ONE, GL_ZERO);
11832                         GL_DepthMask(true);
11833                 }
11834                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11835                 {
11836                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11837                                 continue;
11838                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11839                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11840                         {
11841                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11842                                 if (r_showtris.value > 0)
11843                                 {
11844                                         if (!rsurface.texture->currentlayers->depthmask)
11845                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11846                                         else if (ent == r_refdef.scene.worldentity)
11847                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11848                                         else
11849                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11850                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11851                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11852                                         R_Mesh_ColorPointer(NULL, 0, 0);
11853                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11854                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11855                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11856                                         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);
11857                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11858                                         CHECKGLERROR
11859                                 }
11860                                 if (r_shownormals.value < 0)
11861                                 {
11862                                         qglBegin(GL_LINES);
11863                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11864                                         {
11865                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11866                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11867                                                 qglVertex3f(v[0], v[1], v[2]);
11868                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11869                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11870                                                 qglVertex3f(v[0], v[1], v[2]);
11871                                         }
11872                                         qglEnd();
11873                                         CHECKGLERROR
11874                                 }
11875                                 if (r_shownormals.value > 0)
11876                                 {
11877                                         qglBegin(GL_LINES);
11878                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11879                                         {
11880                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11881                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11882                                                 qglVertex3f(v[0], v[1], v[2]);
11883                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11884                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11885                                                 qglVertex3f(v[0], v[1], v[2]);
11886                                         }
11887                                         qglEnd();
11888                                         CHECKGLERROR
11889                                         qglBegin(GL_LINES);
11890                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11891                                         {
11892                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11893                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11894                                                 qglVertex3f(v[0], v[1], v[2]);
11895                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11896                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11897                                                 qglVertex3f(v[0], v[1], v[2]);
11898                                         }
11899                                         qglEnd();
11900                                         CHECKGLERROR
11901                                         qglBegin(GL_LINES);
11902                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11903                                         {
11904                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11905                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11906                                                 qglVertex3f(v[0], v[1], v[2]);
11907                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11908                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11909                                                 qglVertex3f(v[0], v[1], v[2]);
11910                                         }
11911                                         qglEnd();
11912                                         CHECKGLERROR
11913                                 }
11914                         }
11915                 }
11916                 rsurface.texture = NULL;
11917         }
11918 }
11919
11920 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11921 int r_maxsurfacelist = 0;
11922 const msurface_t **r_surfacelist = NULL;
11923 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11924 {
11925         int i, j, endj, f, flagsmask;
11926         texture_t *t;
11927         dp_model_t *model = r_refdef.scene.worldmodel;
11928         msurface_t *surfaces;
11929         unsigned char *update;
11930         int numsurfacelist = 0;
11931         if (model == NULL)
11932                 return;
11933
11934         if (r_maxsurfacelist < model->num_surfaces)
11935         {
11936                 r_maxsurfacelist = model->num_surfaces;
11937                 if (r_surfacelist)
11938                         Mem_Free((msurface_t**)r_surfacelist);
11939                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11940         }
11941
11942         RSurf_ActiveWorldEntity();
11943
11944         surfaces = model->data_surfaces;
11945         update = model->brushq1.lightmapupdateflags;
11946
11947         // update light styles on this submodel
11948         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11949         {
11950                 model_brush_lightstyleinfo_t *style;
11951                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11952                 {
11953                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11954                         {
11955                                 int *list = style->surfacelist;
11956                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11957                                 for (j = 0;j < style->numsurfaces;j++)
11958                                         update[list[j]] = true;
11959                         }
11960                 }
11961         }
11962
11963         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11964
11965         if (debug)
11966         {
11967                 R_DrawDebugModel();
11968                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11969                 return;
11970         }
11971
11972         f = 0;
11973         t = NULL;
11974         rsurface.uselightmaptexture = false;
11975         rsurface.texture = NULL;
11976         rsurface.rtlight = NULL;
11977         numsurfacelist = 0;
11978         // add visible surfaces to draw list
11979         for (i = 0;i < model->nummodelsurfaces;i++)
11980         {
11981                 j = model->sortedmodelsurfaces[i];
11982                 if (r_refdef.viewcache.world_surfacevisible[j])
11983                         r_surfacelist[numsurfacelist++] = surfaces + j;
11984         }
11985         // update lightmaps if needed
11986         if (model->brushq1.firstrender)
11987         {
11988                 model->brushq1.firstrender = false;
11989                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11990                         if (update[j])
11991                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11992         }
11993         else if (update)
11994         {
11995                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11996                         if (r_refdef.viewcache.world_surfacevisible[j])
11997                                 if (update[j])
11998                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11999         }
12000         // don't do anything if there were no surfaces
12001         if (!numsurfacelist)
12002         {
12003                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12004                 return;
12005         }
12006         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12007         GL_AlphaTest(false);
12008
12009         // add to stats if desired
12010         if (r_speeds.integer && !skysurfaces && !depthonly)
12011         {
12012                 r_refdef.stats.world_surfaces += numsurfacelist;
12013                 for (j = 0;j < numsurfacelist;j++)
12014                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12015         }
12016
12017         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12018 }
12019
12020 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12021 {
12022         int i, j, endj, f, flagsmask;
12023         texture_t *t;
12024         dp_model_t *model = ent->model;
12025         msurface_t *surfaces;
12026         unsigned char *update;
12027         int numsurfacelist = 0;
12028         if (model == NULL)
12029                 return;
12030
12031         if (r_maxsurfacelist < model->num_surfaces)
12032         {
12033                 r_maxsurfacelist = model->num_surfaces;
12034                 if (r_surfacelist)
12035                         Mem_Free((msurface_t **)r_surfacelist);
12036                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12037         }
12038
12039         // if the model is static it doesn't matter what value we give for
12040         // wantnormals and wanttangents, so this logic uses only rules applicable
12041         // to a model, knowing that they are meaningless otherwise
12042         if (ent == r_refdef.scene.worldentity)
12043                 RSurf_ActiveWorldEntity();
12044         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12045                 RSurf_ActiveModelEntity(ent, false, false, false);
12046         else if (prepass)
12047                 RSurf_ActiveModelEntity(ent, true, true, true);
12048         else if (depthonly)
12049                 RSurf_ActiveModelEntity(ent, false, false, false);
12050         else
12051         {
12052                 switch (vid.renderpath)
12053                 {
12054                 case RENDERPATH_GL20:
12055                 case RENDERPATH_CGGL:
12056                         RSurf_ActiveModelEntity(ent, true, true, false);
12057                         break;
12058                 case RENDERPATH_GL13:
12059                 case RENDERPATH_GL11:
12060                         RSurf_ActiveModelEntity(ent, true, false, false);
12061                         break;
12062                 }
12063         }
12064
12065         surfaces = model->data_surfaces;
12066         update = model->brushq1.lightmapupdateflags;
12067
12068         // update light styles
12069         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12070         {
12071                 model_brush_lightstyleinfo_t *style;
12072                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12073                 {
12074                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12075                         {
12076                                 int *list = style->surfacelist;
12077                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12078                                 for (j = 0;j < style->numsurfaces;j++)
12079                                         update[list[j]] = true;
12080                         }
12081                 }
12082         }
12083
12084         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12085
12086         if (debug)
12087         {
12088                 R_DrawDebugModel();
12089                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12090                 return;
12091         }
12092
12093         f = 0;
12094         t = NULL;
12095         rsurface.uselightmaptexture = false;
12096         rsurface.texture = NULL;
12097         rsurface.rtlight = NULL;
12098         numsurfacelist = 0;
12099         // add visible surfaces to draw list
12100         for (i = 0;i < model->nummodelsurfaces;i++)
12101                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12102         // don't do anything if there were no surfaces
12103         if (!numsurfacelist)
12104         {
12105                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12106                 return;
12107         }
12108         // update lightmaps if needed
12109         if (update)
12110         {
12111                 int updated = 0;
12112                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12113                 {
12114                         if (update[j])
12115                         {
12116                                 updated++;
12117                                 R_BuildLightMap(ent, surfaces + j);
12118                         }
12119                 }
12120         }
12121         if (update)
12122                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12123                         if (update[j])
12124                                 R_BuildLightMap(ent, surfaces + j);
12125         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12126         GL_AlphaTest(false);
12127
12128         // add to stats if desired
12129         if (r_speeds.integer && !skysurfaces && !depthonly)
12130         {
12131                 r_refdef.stats.entities_surfaces += numsurfacelist;
12132                 for (j = 0;j < numsurfacelist;j++)
12133                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12134         }
12135
12136         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12137 }
12138
12139 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12140 {
12141         static texture_t texture;
12142         static msurface_t surface;
12143         const msurface_t *surfacelist = &surface;
12144
12145         // fake enough texture and surface state to render this geometry
12146
12147         texture.update_lastrenderframe = -1; // regenerate this texture
12148         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12149         texture.currentskinframe = skinframe;
12150         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12151         texture.specularscalemod = 1;
12152         texture.specularpowermod = 1;
12153
12154         surface.texture = &texture;
12155         surface.num_triangles = numtriangles;
12156         surface.num_firsttriangle = firsttriangle;
12157         surface.num_vertices = numvertices;
12158         surface.num_firstvertex = firstvertex;
12159
12160         // now render it
12161         rsurface.texture = R_GetCurrentTexture(surface.texture);
12162         rsurface.uselightmaptexture = false;
12163         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12164 }
12165
12166 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)
12167 {
12168         static msurface_t surface;
12169         const msurface_t *surfacelist = &surface;
12170
12171         // fake enough texture and surface state to render this geometry
12172
12173         surface.texture = texture;
12174         surface.num_triangles = numtriangles;
12175         surface.num_firsttriangle = firsttriangle;
12176         surface.num_vertices = numvertices;
12177         surface.num_firstvertex = firstvertex;
12178
12179         // now render it
12180         rsurface.texture = R_GetCurrentTexture(surface.texture);
12181         rsurface.uselightmaptexture = false;
12182         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12183 }