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