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