]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
r_glsl_dumpshader: shaderpermutationinfo[i].pretext needs to be checked, otherwise...
[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_frame = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
73 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
74 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
96 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
102
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
111
112 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
113 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
114
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
118
119 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
125 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
126 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
127 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
128
129 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
134
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
139
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
147
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
152
153 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
154
155 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
156
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
158
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
166
167 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
168
169 extern cvar_t v_glslgamma;
170
171 extern qboolean v_flipped_state;
172
173 static struct r_bloomstate_s
174 {
175         qboolean enabled;
176         qboolean hdr;
177
178         int bloomwidth, bloomheight;
179
180         int screentexturewidth, screentextureheight;
181         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
182
183         int bloomtexturewidth, bloomtextureheight;
184         rtexture_t *texture_bloom;
185
186         // arrays for rendering the screen passes
187         float screentexcoord2f[8];
188         float bloomtexcoord2f[8];
189         float offsettexcoord2f[8];
190
191         r_viewport_t viewport;
192 }
193 r_bloomstate;
194
195 r_waterstate_t r_waterstate;
196
197 /// shadow volume bsp struct with automatically growing nodes buffer
198 svbsp_t r_svbsp;
199
200 rtexture_t *r_texture_blanknormalmap;
201 rtexture_t *r_texture_white;
202 rtexture_t *r_texture_grey128;
203 rtexture_t *r_texture_black;
204 rtexture_t *r_texture_notexture;
205 rtexture_t *r_texture_whitecube;
206 rtexture_t *r_texture_normalizationcube;
207 rtexture_t *r_texture_fogattenuation;
208 rtexture_t *r_texture_gammaramps;
209 unsigned int r_texture_gammaramps_serial;
210 //rtexture_t *r_texture_fogintensity;
211
212 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
213 unsigned int r_numqueries;
214 unsigned int r_maxqueries;
215
216 typedef struct r_qwskincache_s
217 {
218         char name[MAX_QPATH];
219         skinframe_t *skinframe;
220 }
221 r_qwskincache_t;
222
223 static r_qwskincache_t *r_qwskincache;
224 static int r_qwskincache_size;
225
226 /// vertex coordinates for a quad that covers the screen exactly
227 const float r_screenvertex3f[12] =
228 {
229         0, 0, 0,
230         1, 0, 0,
231         1, 1, 0,
232         0, 1, 0
233 };
234
235 extern void R_DrawModelShadows(void);
236
237 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
238 {
239         int i;
240         for (i = 0;i < verts;i++)
241         {
242                 out[0] = in[0] * r;
243                 out[1] = in[1] * g;
244                 out[2] = in[2] * b;
245                 out[3] = in[3];
246                 in += 4;
247                 out += 4;
248         }
249 }
250
251 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
252 {
253         int i;
254         for (i = 0;i < verts;i++)
255         {
256                 out[0] = r;
257                 out[1] = g;
258                 out[2] = b;
259                 out[3] = a;
260                 out += 4;
261         }
262 }
263
264 // FIXME: move this to client?
265 void FOG_clear(void)
266 {
267         if (gamemode == GAME_NEHAHRA)
268         {
269                 Cvar_Set("gl_fogenable", "0");
270                 Cvar_Set("gl_fogdensity", "0.2");
271                 Cvar_Set("gl_fogred", "0.3");
272                 Cvar_Set("gl_foggreen", "0.3");
273                 Cvar_Set("gl_fogblue", "0.3");
274         }
275         r_refdef.fog_density = 0;
276         r_refdef.fog_red = 0;
277         r_refdef.fog_green = 0;
278         r_refdef.fog_blue = 0;
279         r_refdef.fog_alpha = 1;
280         r_refdef.fog_start = 0;
281         r_refdef.fog_end = 16384;
282         r_refdef.fog_height = 1<<30;
283         r_refdef.fog_fadedepth = 128;
284 }
285
286 static void R_BuildBlankTextures(void)
287 {
288         unsigned char data[4];
289         data[2] = 128; // normal X
290         data[1] = 128; // normal Y
291         data[0] = 255; // normal Z
292         data[3] = 128; // height
293         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
294         data[0] = 255;
295         data[1] = 255;
296         data[2] = 255;
297         data[3] = 255;
298         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
299         data[0] = 128;
300         data[1] = 128;
301         data[2] = 128;
302         data[3] = 255;
303         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
304         data[0] = 0;
305         data[1] = 0;
306         data[2] = 0;
307         data[3] = 255;
308         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
309 }
310
311 static void R_BuildNoTexture(void)
312 {
313         int x, y;
314         unsigned char pix[16][16][4];
315         // this makes a light grey/dark grey checkerboard texture
316         for (y = 0;y < 16;y++)
317         {
318                 for (x = 0;x < 16;x++)
319                 {
320                         if ((y < 8) ^ (x < 8))
321                         {
322                                 pix[y][x][0] = 128;
323                                 pix[y][x][1] = 128;
324                                 pix[y][x][2] = 128;
325                                 pix[y][x][3] = 255;
326                         }
327                         else
328                         {
329                                 pix[y][x][0] = 64;
330                                 pix[y][x][1] = 64;
331                                 pix[y][x][2] = 64;
332                                 pix[y][x][3] = 255;
333                         }
334                 }
335         }
336         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
337 }
338
339 static void R_BuildWhiteCube(void)
340 {
341         unsigned char data[6*1*1*4];
342         memset(data, 255, sizeof(data));
343         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
344 }
345
346 static void R_BuildNormalizationCube(void)
347 {
348         int x, y, side;
349         vec3_t v;
350         vec_t s, t, intensity;
351 #define NORMSIZE 64
352         unsigned char *data;
353         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
354         for (side = 0;side < 6;side++)
355         {
356                 for (y = 0;y < NORMSIZE;y++)
357                 {
358                         for (x = 0;x < NORMSIZE;x++)
359                         {
360                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
361                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
362                                 switch(side)
363                                 {
364                                 default:
365                                 case 0:
366                                         v[0] = 1;
367                                         v[1] = -t;
368                                         v[2] = -s;
369                                         break;
370                                 case 1:
371                                         v[0] = -1;
372                                         v[1] = -t;
373                                         v[2] = s;
374                                         break;
375                                 case 2:
376                                         v[0] = s;
377                                         v[1] = 1;
378                                         v[2] = t;
379                                         break;
380                                 case 3:
381                                         v[0] = s;
382                                         v[1] = -1;
383                                         v[2] = -t;
384                                         break;
385                                 case 4:
386                                         v[0] = s;
387                                         v[1] = -t;
388                                         v[2] = 1;
389                                         break;
390                                 case 5:
391                                         v[0] = -s;
392                                         v[1] = -t;
393                                         v[2] = -1;
394                                         break;
395                                 }
396                                 intensity = 127.0f / sqrt(DotProduct(v, v));
397                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
398                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
399                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
400                                 data[((side*64+y)*64+x)*4+3] = 255;
401                         }
402                 }
403         }
404         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
405         Mem_Free(data);
406 }
407
408 static void R_BuildFogTexture(void)
409 {
410         int x, b;
411 #define FOGWIDTH 256
412         unsigned char data1[FOGWIDTH][4];
413         //unsigned char data2[FOGWIDTH][4];
414         double d, r, alpha;
415
416         r_refdef.fogmasktable_start = r_refdef.fog_start;
417         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
418         r_refdef.fogmasktable_range = r_refdef.fogrange;
419         r_refdef.fogmasktable_density = r_refdef.fog_density;
420
421         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
422         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
423         {
424                 d = (x * r - r_refdef.fogmasktable_start);
425                 if(developer_extra.integer)
426                         Con_DPrintf("%f ", d);
427                 d = max(0, d);
428                 if (r_fog_exp2.integer)
429                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
430                 else
431                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
432                 if(developer_extra.integer)
433                         Con_DPrintf(" : %f ", alpha);
434                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
435                 if(developer_extra.integer)
436                         Con_DPrintf(" = %f\n", alpha);
437                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
438         }
439
440         for (x = 0;x < FOGWIDTH;x++)
441         {
442                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
443                 data1[x][0] = b;
444                 data1[x][1] = b;
445                 data1[x][2] = b;
446                 data1[x][3] = 255;
447                 //data2[x][0] = 255 - b;
448                 //data2[x][1] = 255 - b;
449                 //data2[x][2] = 255 - b;
450                 //data2[x][3] = 255;
451         }
452         if (r_texture_fogattenuation)
453         {
454                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
455                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
456         }
457         else
458         {
459                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
460                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
461         }
462 }
463
464 //=======================================================================================================================================================
465
466 static const char *builtinshaderstring =
467 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
468 "// written by Forest 'LordHavoc' Hale\n"
469 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
470 "\n"
471 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
472 "# define USEFOG\n"
473 "#endif\n"
474 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
475 "#define USELIGHTMAP\n"
476 "#endif\n"
477 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
478 "#define USEEYEVECTOR\n"
479 "#endif\n"
480 "\n"
481 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
482 "# extension GL_ARB_texture_rectangle : enable\n"
483 "#endif\n"
484 "\n"
485 "#ifdef USESHADOWMAP2D\n"
486 "# ifdef GL_EXT_gpu_shader4\n"
487 "#   extension GL_EXT_gpu_shader4 : enable\n"
488 "# endif\n"
489 "# ifdef GL_ARB_texture_gather\n"
490 "#   extension GL_ARB_texture_gather : enable\n"
491 "# else\n"
492 "#   ifdef GL_AMD_texture_texture4\n"
493 "#     extension GL_AMD_texture_texture4 : enable\n"
494 "#   endif\n"
495 "# endif\n"
496 "#endif\n"
497 "\n"
498 "#ifdef USESHADOWMAPCUBE\n"
499 "# extension GL_EXT_gpu_shader4 : enable\n"
500 "#endif\n"
501 "\n"
502 "//#ifdef USESHADOWSAMPLER\n"
503 "//# extension GL_ARB_shadow : enable\n"
504 "//#endif\n"
505 "\n"
506 "//#ifdef __GLSL_CG_DATA_TYPES\n"
507 "//# define myhalf half\n"
508 "//# define myhalf2 half2\n"
509 "//# define myhalf3 half3\n"
510 "//# define myhalf4 half4\n"
511 "//#else\n"
512 "# define myhalf float\n"
513 "# define myhalf2 vec2\n"
514 "# define myhalf3 vec3\n"
515 "# define myhalf4 vec4\n"
516 "//#endif\n"
517 "\n"
518 "#ifdef VERTEX_SHADER\n"
519 "uniform mat4 ModelViewProjectionMatrix;\n"
520 "#endif\n"
521 "\n"
522 "#ifdef MODE_DEPTH_OR_SHADOW\n"
523 "#ifdef VERTEX_SHADER\n"
524 "void main(void)\n"
525 "{\n"
526 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
527 "}\n"
528 "#endif\n"
529 "#else // !MODE_DEPTH_ORSHADOW\n"
530 "\n"
531 "\n"
532 "\n"
533 "\n"
534 "#ifdef MODE_SHOWDEPTH\n"
535 "#ifdef VERTEX_SHADER\n"
536 "void main(void)\n"
537 "{\n"
538 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
539 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
540 "}\n"
541 "#endif\n"
542 "\n"
543 "#ifdef FRAGMENT_SHADER\n"
544 "void main(void)\n"
545 "{\n"
546 "       gl_FragColor = gl_Color;\n"
547 "}\n"
548 "#endif\n"
549 "#else // !MODE_SHOWDEPTH\n"
550 "\n"
551 "\n"
552 "\n"
553 "\n"
554 "#ifdef MODE_POSTPROCESS\n"
555 "varying vec2 TexCoord1;\n"
556 "varying vec2 TexCoord2;\n"
557 "\n"
558 "#ifdef VERTEX_SHADER\n"
559 "void main(void)\n"
560 "{\n"
561 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
562 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
563 "#ifdef USEBLOOM\n"
564 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
565 "#endif\n"
566 "}\n"
567 "#endif\n"
568 "\n"
569 "#ifdef FRAGMENT_SHADER\n"
570 "uniform sampler2D Texture_First;\n"
571 "#ifdef USEBLOOM\n"
572 "uniform sampler2D Texture_Second;\n"
573 "#endif\n"
574 "#ifdef USEGAMMARAMPS\n"
575 "uniform sampler2D Texture_GammaRamps;\n"
576 "#endif\n"
577 "#ifdef USESATURATION\n"
578 "uniform float Saturation;\n"
579 "#endif\n"
580 "#ifdef USEVIEWTINT\n"
581 "uniform vec4 ViewTintColor;\n"
582 "#endif\n"
583 "//uncomment these if you want to use them:\n"
584 "uniform vec4 UserVec1;\n"
585 "// uniform vec4 UserVec2;\n"
586 "// uniform vec4 UserVec3;\n"
587 "// uniform vec4 UserVec4;\n"
588 "// uniform float ClientTime;\n"
589 "uniform vec2 PixelSize;\n"
590 "void main(void)\n"
591 "{\n"
592 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
593 "#ifdef USEBLOOM\n"
594 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
595 "#endif\n"
596 "#ifdef USEVIEWTINT\n"
597 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
598 "#endif\n"
599 "\n"
600 "#ifdef USEPOSTPROCESSING\n"
601 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
602 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
603 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
604 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
605 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
606 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
607 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
608 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
609 "#endif\n"
610 "\n"
611 "#ifdef USESATURATION\n"
612 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
613 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
614 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
615 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
616 "#endif\n"
617 "\n"
618 "#ifdef USEGAMMARAMPS\n"
619 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
620 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
621 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
622 "#endif\n"
623 "}\n"
624 "#endif\n"
625 "#else // !MODE_POSTPROCESS\n"
626 "\n"
627 "\n"
628 "\n"
629 "\n"
630 "#ifdef MODE_GENERIC\n"
631 "#ifdef USEDIFFUSE\n"
632 "varying vec2 TexCoord1;\n"
633 "#endif\n"
634 "#ifdef USESPECULAR\n"
635 "varying vec2 TexCoord2;\n"
636 "#endif\n"
637 "#ifdef VERTEX_SHADER\n"
638 "void main(void)\n"
639 "{\n"
640 "       gl_FrontColor = gl_Color;\n"
641 "#ifdef USEDIFFUSE\n"
642 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
643 "#endif\n"
644 "#ifdef USESPECULAR\n"
645 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
646 "#endif\n"
647 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
648 "}\n"
649 "#endif\n"
650 "\n"
651 "#ifdef FRAGMENT_SHADER\n"
652 "#ifdef USEDIFFUSE\n"
653 "uniform sampler2D Texture_First;\n"
654 "#endif\n"
655 "#ifdef USESPECULAR\n"
656 "uniform sampler2D Texture_Second;\n"
657 "#endif\n"
658 "\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FragColor = gl_Color;\n"
662 "#ifdef USEDIFFUSE\n"
663 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
664 "#endif\n"
665 "\n"
666 "#ifdef USESPECULAR\n"
667 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
668 "# ifdef USECOLORMAPPING\n"
669 "       gl_FragColor *= tex2;\n"
670 "# endif\n"
671 "# ifdef USEGLOW\n"
672 "       gl_FragColor += tex2;\n"
673 "# endif\n"
674 "# ifdef USEVERTEXTEXTUREBLEND\n"
675 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
676 "# endif\n"
677 "#endif\n"
678 "}\n"
679 "#endif\n"
680 "#else // !MODE_GENERIC\n"
681 "\n"
682 "\n"
683 "\n"
684 "\n"
685 "#ifdef MODE_BLOOMBLUR\n"
686 "varying TexCoord;\n"
687 "#ifdef VERTEX_SHADER\n"
688 "void main(void)\n"
689 "{\n"
690 "       gl_FrontColor = gl_Color;\n"
691 "       TexCoord = gl_MultiTexCoord0.xy;\n"
692 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
693 "}\n"
694 "#endif\n"
695 "\n"
696 "#ifdef FRAGMENT_SHADER\n"
697 "uniform sampler2D Texture_First;\n"
698 "uniform vec4 BloomBlur_Parameters;\n"
699 "\n"
700 "void main(void)\n"
701 "{\n"
702 "       int i;\n"
703 "       vec2 tc = TexCoord;\n"
704 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
705 "       tc += BloomBlur_Parameters.xy;\n"
706 "       for (i = 1;i < SAMPLES;i++)\n"
707 "       {\n"
708 "               color += texture2D(Texture_First, tc).rgb;\n"
709 "               tc += BloomBlur_Parameters.xy;\n"
710 "       }\n"
711 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
712 "}\n"
713 "#endif\n"
714 "#else // !MODE_BLOOMBLUR\n"
715 "#ifdef MODE_REFRACTION\n"
716 "varying vec2 TexCoord;\n"
717 "varying vec4 ModelViewProjectionPosition;\n"
718 "uniform mat4 TexMatrix;\n"
719 "#ifdef VERTEX_SHADER\n"
720 "\n"
721 "void main(void)\n"
722 "{\n"
723 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
724 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
725 "       ModelViewProjectionPosition = gl_Position;\n"
726 "}\n"
727 "#endif\n"
728 "\n"
729 "#ifdef FRAGMENT_SHADER\n"
730 "uniform sampler2D Texture_Normal;\n"
731 "uniform sampler2D Texture_Refraction;\n"
732 "uniform sampler2D Texture_Reflection;\n"
733 "\n"
734 "uniform vec4 DistortScaleRefractReflect;\n"
735 "uniform vec4 ScreenScaleRefractReflect;\n"
736 "uniform vec4 ScreenCenterRefractReflect;\n"
737 "uniform vec4 RefractColor;\n"
738 "uniform vec4 ReflectColor;\n"
739 "uniform float ReflectFactor;\n"
740 "uniform float ReflectOffset;\n"
741 "\n"
742 "void main(void)\n"
743 "{\n"
744 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
745 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
746 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
747 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
748 "       // FIXME temporary hack to detect the case that the reflection\n"
749 "       // gets blackened at edges due to leaving the area that contains actual\n"
750 "       // content.\n"
751 "       // Remove this 'ack once we have a better way to stop this thing from\n"
752 "       // 'appening.\n"
753 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
754 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
755 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
756 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
757 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
758 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
759 "}\n"
760 "#endif\n"
761 "#else // !MODE_REFRACTION\n"
762 "\n"
763 "\n"
764 "\n"
765 "\n"
766 "#ifdef MODE_WATER\n"
767 "varying vec2 TexCoord;\n"
768 "varying vec3 EyeVector;\n"
769 "varying vec4 ModelViewProjectionPosition;\n"
770 "#ifdef VERTEX_SHADER\n"
771 "uniform vec3 EyePosition;\n"
772 "uniform mat4 TexMatrix;\n"
773 "\n"
774 "void main(void)\n"
775 "{\n"
776 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
777 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
778 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
779 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
780 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
781 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
782 "       ModelViewProjectionPosition = gl_Position;\n"
783 "}\n"
784 "#endif\n"
785 "\n"
786 "#ifdef FRAGMENT_SHADER\n"
787 "uniform sampler2D Texture_Normal;\n"
788 "uniform sampler2D Texture_Refraction;\n"
789 "uniform sampler2D Texture_Reflection;\n"
790 "\n"
791 "uniform vec4 DistortScaleRefractReflect;\n"
792 "uniform vec4 ScreenScaleRefractReflect;\n"
793 "uniform vec4 ScreenCenterRefractReflect;\n"
794 "uniform vec4 RefractColor;\n"
795 "uniform vec4 ReflectColor;\n"
796 "uniform float ReflectFactor;\n"
797 "uniform float ReflectOffset;\n"
798 "\n"
799 "void main(void)\n"
800 "{\n"
801 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
802 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
803 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
804 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
805 "       // FIXME temporary hack to detect the case that the reflection\n"
806 "       // gets blackened at edges due to leaving the area that contains actual\n"
807 "       // content.\n"
808 "       // Remove this 'ack once we have a better way to stop this thing from\n"
809 "       // 'appening.\n"
810 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
811 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
812 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
813 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
814 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
815 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
816 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
817 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
818 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
819 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
820 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
821 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
822 "}\n"
823 "#endif\n"
824 "#else // !MODE_WATER\n"
825 "\n"
826 "\n"
827 "\n"
828 "\n"
829 "// common definitions between vertex shader and fragment shader:\n"
830 "\n"
831 "varying vec2 TexCoord;\n"
832 "#ifdef USEVERTEXTEXTUREBLEND\n"
833 "varying vec2 TexCoord2;\n"
834 "#endif\n"
835 "#ifdef USELIGHTMAP\n"
836 "varying vec2 TexCoordLightmap;\n"
837 "#endif\n"
838 "\n"
839 "#ifdef MODE_LIGHTSOURCE\n"
840 "varying vec3 CubeVector;\n"
841 "#endif\n"
842 "\n"
843 "#ifdef MODE_LIGHTSOURCE\n"
844 "varying vec3 LightVector;\n"
845 "#endif\n"
846 "#if defined(MODE_LIGHTDIRECTION)\n"
847 "varying vec3 LightVector;\n"
848 "#endif\n"
849 "\n"
850 "#ifdef USEEYEVECTOR\n"
851 "varying vec3 EyeVector;\n"
852 "#endif\n"
853 "#ifdef USEFOG\n"
854 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
855 "#endif\n"
856 "\n"
857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
858 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
859 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
860 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
861 "#endif\n"
862 "\n"
863 "#ifdef USEREFLECTION\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "#endif\n"
866 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
867 "uniform vec3 LightPosition;\n"
868 "varying vec4 ModelViewPosition;\n"
869 "#endif\n"
870 "\n"
871 "#ifdef MODE_LIGHTSOURCE\n"
872 "uniform vec3 LightPosition;\n"
873 "#endif\n"
874 "uniform vec3 EyePosition;\n"
875 "#ifdef MODE_LIGHTDIRECTION\n"
876 "uniform vec3 LightDir;\n"
877 "#endif\n"
878 "uniform vec4 FogPlane;\n"
879 "\n"
880 "\n"
881 "\n"
882 "\n"
883 "\n"
884 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
885 "\n"
886 "// fragment shader specific:\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "\n"
889 "uniform sampler2D Texture_Normal;\n"
890 "uniform sampler2D Texture_Color;\n"
891 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
892 "uniform sampler2D Texture_Gloss;\n"
893 "//#endif\n"
894 "#ifdef USEGLOW\n"
895 "uniform sampler2D Texture_Glow;\n"
896 "#endif\n"
897 "#ifdef USEVERTEXTEXTUREBLEND\n"
898 "uniform sampler2D Texture_SecondaryNormal;\n"
899 "uniform sampler2D Texture_SecondaryColor;\n"
900 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
901 "uniform sampler2D Texture_SecondaryGloss;\n"
902 "//#endif\n"
903 "#ifdef USEGLOW\n"
904 "uniform sampler2D Texture_SecondaryGlow;\n"
905 "#endif\n"
906 "#endif\n"
907 "#ifdef USECOLORMAPPING\n"
908 "uniform sampler2D Texture_Pants;\n"
909 "uniform sampler2D Texture_Shirt;\n"
910 "#endif\n"
911 "#ifdef USEFOG\n"
912 "uniform sampler2D Texture_FogMask;\n"
913 "#endif\n"
914 "#ifdef USELIGHTMAP\n"
915 "uniform sampler2D Texture_Lightmap;\n"
916 "#endif\n"
917 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
918 "uniform sampler2D Texture_Deluxemap;\n"
919 "#endif\n"
920 "#ifdef USEREFLECTION\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "#endif\n"
923 "\n"
924 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
925 "uniform sampler2DRect Texture_ScreenDepth;\n"
926 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
927 "#endif\n"
928 "#ifdef USEDEFERREDLIGHTMAP\n"
929 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
930 "uniform sampler2DRect Texture_ScreenSpecular;\n"
931 "#endif\n"
932 "\n"
933 "uniform myhalf3 Color_Pants;\n"
934 "uniform myhalf3 Color_Shirt;\n"
935 "uniform myhalf3 FogColor;\n"
936 "\n"
937 "#ifdef USEFOG\n"
938 "uniform float FogRangeRecip;\n"
939 "uniform float FogPlaneViewDist;\n"
940 "uniform float FogHeightFade;\n"
941 "float FogVertex(void)\n"
942 "{\n"
943 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
944 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
945 "       float fogfrac;\n"
946 "#ifdef USEFOGOUTSIDE\n"
947 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
948 "#else\n"
949 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
950 "#endif\n"
951 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
952 "}\n"
953 "#endif\n"
954 "\n"
955 "#ifdef USEOFFSETMAPPING\n"
956 "uniform float OffsetMapping_Scale;\n"
957 "vec2 OffsetMapping(vec2 TexCoord)\n"
958 "{\n"
959 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
960 "       // 14 sample relief mapping: linear search and then binary search\n"
961 "       // this basically steps forward a small amount repeatedly until it finds\n"
962 "       // itself inside solid, then jitters forward and back using decreasing\n"
963 "       // amounts to find the impact\n"
964 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
965 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
966 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
967 "       vec3 RT = vec3(TexCoord, 1);\n"
968 "       OffsetVector *= 0.1;\n"
969 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
970 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
971 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
972 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
973 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
974 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
975 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
976 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
977 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
978 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
979 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
980 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
981 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
982 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
983 "       return RT.xy;\n"
984 "#else\n"
985 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
986 "       // this basically moves forward the full distance, and then backs up based\n"
987 "       // on height of samples\n"
988 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
989 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
990 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
991 "       TexCoord += OffsetVector;\n"
992 "       OffsetVector *= 0.333;\n"
993 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
994 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
995 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
996 "       return TexCoord;\n"
997 "#endif\n"
998 "}\n"
999 "#endif // USEOFFSETMAPPING\n"
1000 "\n"
1001 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1002 "uniform sampler2D Texture_Attenuation;\n"
1003 "uniform samplerCube Texture_Cube;\n"
1004 "\n"
1005 "#ifdef USESHADOWMAPRECT\n"
1006 "# ifdef USESHADOWSAMPLER\n"
1007 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1008 "# else\n"
1009 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1010 "# endif\n"
1011 "#endif\n"
1012 "\n"
1013 "#ifdef USESHADOWMAP2D\n"
1014 "# ifdef USESHADOWSAMPLER\n"
1015 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1016 "# else\n"
1017 "uniform sampler2D Texture_ShadowMap2D;\n"
1018 "# endif\n"
1019 "#endif\n"
1020 "\n"
1021 "#ifdef USESHADOWMAPVSDCT\n"
1022 "uniform samplerCube Texture_CubeProjection;\n"
1023 "#endif\n"
1024 "\n"
1025 "#ifdef USESHADOWMAPCUBE\n"
1026 "# ifdef USESHADOWSAMPLER\n"
1027 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1028 "# else\n"
1029 "uniform samplerCube Texture_ShadowMapCube;\n"
1030 "# endif\n"
1031 "#endif\n"
1032 "\n"
1033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1034 "uniform vec2 ShadowMap_TextureScale;\n"
1035 "uniform vec4 ShadowMap_Parameters;\n"
1036 "#endif\n"
1037 "\n"
1038 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1039 "# ifndef USESHADOWMAPVSDCT\n"
1040 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1041 "{\n"
1042 "       vec3 adir = abs(dir);\n"
1043 "       vec2 tc;\n"
1044 "       vec2 offset;\n"
1045 "       float ma;\n"
1046 "       if (adir.x > adir.y)\n"
1047 "       {\n"
1048 "               if (adir.x > adir.z) // X\n"
1049 "               {\n"
1050 "                       ma = adir.x;\n"
1051 "                       tc = dir.zy;\n"
1052 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1053 "               }\n"
1054 "               else // Z\n"
1055 "               {\n"
1056 "                       ma = adir.z;\n"
1057 "                       tc = dir.xy;\n"
1058 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1059 "               }\n"
1060 "       }\n"
1061 "       else\n"
1062 "       {\n"
1063 "               if (adir.y > adir.z) // Y\n"
1064 "               {\n"
1065 "                       ma = adir.y;\n"
1066 "                       tc = dir.xz;\n"
1067 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1068 "               }\n"
1069 "               else // Z\n"
1070 "               {\n"
1071 "                       ma = adir.z;\n"
1072 "                       tc = dir.xy;\n"
1073 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1074 "               }\n"
1075 "       }\n"
1076 "\n"
1077 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1078 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1079 "       stc.z += ShadowMap_Parameters.z;\n"
1080 "       return stc;\n"
1081 "}\n"
1082 "# else\n"
1083 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1084 "{\n"
1085 "       vec3 adir = abs(dir);\n"
1086 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1087 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1088 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1089 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1090 "       stc.z += ShadowMap_Parameters.z;\n"
1091 "       return stc;\n"
1092 "}\n"
1093 "# endif\n"
1094 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1095 "\n"
1096 "#ifdef USESHADOWMAPCUBE\n"
1097 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1098 "{\n"
1099 "       vec3 adir = abs(dir);\n"
1100 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1101 "}\n"
1102 "#endif\n"
1103 "\n"
1104 "# ifdef USESHADOWMAPRECT\n"
1105 "float ShadowMapCompare(vec3 dir)\n"
1106 "{\n"
1107 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1108 "       float f;\n"
1109 "#  ifdef USESHADOWSAMPLER\n"
1110 "\n"
1111 "#    ifdef USESHADOWMAPPCF\n"
1112 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1113 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1114 "#    else\n"
1115 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1116 "#    endif\n"
1117 "\n"
1118 "#  else\n"
1119 "\n"
1120 "#    ifdef USESHADOWMAPPCF\n"
1121 "#      if USESHADOWMAPPCF > 1\n"
1122 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1123 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1124 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1125 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1126 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1127 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1128 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1129 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1130 "#      else\n"
1131 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1132 "       vec2 offset = fract(shadowmaptc.xy);\n"
1133 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1134 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1135 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1136 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1137 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1138 "#      endif\n"
1139 "#    else\n"
1140 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1141 "#    endif\n"
1142 "\n"
1143 "#  endif\n"
1144 "       return f;\n"
1145 "}\n"
1146 "# endif\n"
1147 "\n"
1148 "# ifdef USESHADOWMAP2D\n"
1149 "float ShadowMapCompare(vec3 dir)\n"
1150 "{\n"
1151 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1152 "       float f;\n"
1153 "\n"
1154 "#  ifdef USESHADOWSAMPLER\n"
1155 "#    ifdef USESHADOWMAPPCF\n"
1156 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1157 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1158 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1159 "#    else\n"
1160 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1161 "#    endif\n"
1162 "#  else\n"
1163 "#    ifdef USESHADOWMAPPCF\n"
1164 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1165 "#      ifdef GL_ARB_texture_gather\n"
1166 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1167 "#      else\n"
1168 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1169 "#      endif\n"
1170 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1171 "       center *= ShadowMap_TextureScale;\n"
1172 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1173 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1174 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1175 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1176 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1177 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1178 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1179 "#     else\n"
1180 "#      ifdef GL_EXT_gpu_shader4\n"
1181 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1182 "#      else\n"
1183 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1184 "#      endif\n"
1185 "#      if USESHADOWMAPPCF > 1\n"
1186 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1187 "       center *= ShadowMap_TextureScale;\n"
1188 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1189 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1190 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1191 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1192 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1193 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1194 "#      else\n"
1195 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1196 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1197 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1198 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1199 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1200 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1201 "#      endif\n"
1202 "#     endif\n"
1203 "#    else\n"
1204 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1205 "#    endif\n"
1206 "#  endif\n"
1207 "       return f;\n"
1208 "}\n"
1209 "# endif\n"
1210 "\n"
1211 "# ifdef USESHADOWMAPCUBE\n"
1212 "float ShadowMapCompare(vec3 dir)\n"
1213 "{\n"
1214 "       // apply depth texture cubemap as light filter\n"
1215 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1216 "       float f;\n"
1217 "#  ifdef USESHADOWSAMPLER\n"
1218 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1219 "#  else\n"
1220 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1221 "#  endif\n"
1222 "       return f;\n"
1223 "}\n"
1224 "# endif\n"
1225 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1226 "#endif // FRAGMENT_SHADER\n"
1227 "\n"
1228 "\n"
1229 "\n"
1230 "\n"
1231 "#ifdef MODE_DEFERREDGEOMETRY\n"
1232 "#ifdef VERTEX_SHADER\n"
1233 "uniform mat4 TexMatrix;\n"
1234 "#ifdef USEVERTEXTEXTUREBLEND\n"
1235 "uniform mat4 BackgroundTexMatrix;\n"
1236 "#endif\n"
1237 "uniform mat4 ModelViewMatrix;\n"
1238 "void main(void)\n"
1239 "{\n"
1240 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1241 "#ifdef USEVERTEXTEXTUREBLEND\n"
1242 "       gl_FrontColor = gl_Color;\n"
1243 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1244 "#endif\n"
1245 "\n"
1246 "       // transform unnormalized eye direction into tangent space\n"
1247 "#ifdef USEOFFSETMAPPING\n"
1248 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1249 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1250 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1251 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1252 "#endif\n"
1253 "\n"
1254 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1255 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1256 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1257 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1258 "}\n"
1259 "#endif // VERTEX_SHADER\n"
1260 "\n"
1261 "#ifdef FRAGMENT_SHADER\n"
1262 "void main(void)\n"
1263 "{\n"
1264 "#ifdef USEOFFSETMAPPING\n"
1265 "       // apply offsetmapping\n"
1266 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1267 "#define TexCoord TexCoordOffset\n"
1268 "#endif\n"
1269 "\n"
1270 "#ifdef USEALPHAKILL\n"
1271 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1272 "               discard;\n"
1273 "#endif\n"
1274 "\n"
1275 "#ifdef USEVERTEXTEXTUREBLEND\n"
1276 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1277 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1278 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1279 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1280 "#endif\n"
1281 "\n"
1282 "#ifdef USEVERTEXTEXTUREBLEND\n"
1283 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1284 "#else\n"
1285 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1286 "#endif\n"
1287 "\n"
1288 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1289 "}\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1292 "\n"
1293 "\n"
1294 "\n"
1295 "\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1299 "void main(void)\n"
1300 "{\n"
1301 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1303 "}\n"
1304 "#endif // VERTEX_SHADER\n"
1305 "\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1315 "#endif\n"
1316 "void main(void)\n"
1317 "{\n"
1318 "       // calculate viewspace pixel position\n"
1319 "       vec3 position;\n"
1320 "       position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1321 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1322 "       // decode viewspace pixel normal\n"
1323 "       myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1324 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1325 "       // surfacenormal = pixel normal in viewspace\n"
1326 "       // LightVector = pixel to light in viewspace\n"
1327 "       // CubeVector = position in lightspace\n"
1328 "       // eyevector = pixel to view in viewspace\n"
1329 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1330 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1331 "#ifdef USEDIFFUSE\n"
1332 "       // calculate diffuse shading\n"
1333 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1334 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1335 "#endif\n"
1336 "#ifdef USESPECULAR\n"
1337 "       // calculate directional shading\n"
1338 "       vec3 eyevector = position * -1.0;\n"
1339 "#  ifdef USEEXACTSPECULARMATH\n"
1340 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1341 "#  else\n"
1342 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1343 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1344 "#  endif\n"
1345 "#endif\n"
1346 "\n"
1347 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1348 "       fade *= ShadowMapCompare(CubeVector);\n"
1349 "#endif\n"
1350 "\n"
1351 "#ifdef USEDIFFUSE\n"
1352 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1353 "#else\n"
1354 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1355 "#endif\n"
1356 "#ifdef USESPECULAR\n"
1357 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1358 "#else\n"
1359 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1360 "#endif\n"
1361 "\n"
1362 "# ifdef USECUBEFILTER\n"
1363 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1364 "       gl_FragData[0] *= cubecolor;\n"
1365 "       gl_FragData[1] *= cubecolor;\n"
1366 "# endif\n"
1367 "}\n"
1368 "#endif // FRAGMENT_SHADER\n"
1369 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1370 "\n"
1371 "\n"
1372 "\n"
1373 "\n"
1374 "#ifdef VERTEX_SHADER\n"
1375 "uniform mat4 TexMatrix;\n"
1376 "#ifdef USEVERTEXTEXTUREBLEND\n"
1377 "uniform mat4 BackgroundTexMatrix;\n"
1378 "#endif\n"
1379 "#ifdef MODE_LIGHTSOURCE\n"
1380 "uniform mat4 ModelToLight;\n"
1381 "#endif\n"
1382 "void main(void)\n"
1383 "{\n"
1384 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1385 "       gl_FrontColor = gl_Color;\n"
1386 "#endif\n"
1387 "       // copy the surface texcoord\n"
1388 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1391 "#endif\n"
1392 "#ifdef USELIGHTMAP\n"
1393 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1394 "#endif\n"
1395 "\n"
1396 "#ifdef MODE_LIGHTSOURCE\n"
1397 "       // transform vertex position into light attenuation/cubemap space\n"
1398 "       // (-1 to +1 across the light box)\n"
1399 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1400 "\n"
1401 "# ifdef USEDIFFUSE\n"
1402 "       // transform unnormalized light direction into tangent space\n"
1403 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1404 "       //  normalize it per pixel)\n"
1405 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1406 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1407 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1408 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1409 "# endif\n"
1410 "#endif\n"
1411 "\n"
1412 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1413 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1414 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1415 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1416 "#endif\n"
1417 "\n"
1418 "       // transform unnormalized eye direction into tangent space\n"
1419 "#ifdef USEEYEVECTOR\n"
1420 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1421 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1422 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1423 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1424 "#endif\n"
1425 "\n"
1426 "#ifdef USEFOG\n"
1427 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1428 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1429 "#endif\n"
1430 "\n"
1431 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1432 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1433 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1434 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1435 "#endif\n"
1436 "\n"
1437 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1438 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1439 "\n"
1440 "#ifdef USEREFLECTION\n"
1441 "       ModelViewProjectionPosition = gl_Position;\n"
1442 "#endif\n"
1443 "}\n"
1444 "#endif // VERTEX_SHADER\n"
1445 "\n"
1446 "\n"
1447 "\n"
1448 "\n"
1449 "#ifdef FRAGMENT_SHADER\n"
1450 "#ifdef USEDEFERREDLIGHTMAP\n"
1451 "uniform myhalf3 DeferredMod_Diffuse;\n"
1452 "uniform myhalf3 DeferredMod_Specular;\n"
1453 "#endif\n"
1454 "uniform myhalf3 Color_Ambient;\n"
1455 "uniform myhalf3 Color_Diffuse;\n"
1456 "uniform myhalf3 Color_Specular;\n"
1457 "uniform myhalf SpecularPower;\n"
1458 "#ifdef USEGLOW\n"
1459 "uniform myhalf3 Color_Glow;\n"
1460 "#endif\n"
1461 "uniform myhalf Alpha;\n"
1462 "#ifdef USEREFLECTION\n"
1463 "uniform vec4 DistortScaleRefractReflect;\n"
1464 "uniform vec4 ScreenScaleRefractReflect;\n"
1465 "uniform vec4 ScreenCenterRefractReflect;\n"
1466 "uniform myhalf4 ReflectColor;\n"
1467 "#endif\n"
1468 "#ifdef MODE_LIGHTDIRECTION\n"
1469 "uniform myhalf3 LightColor;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTSOURCE\n"
1472 "uniform myhalf3 LightColor;\n"
1473 "#endif\n"
1474 "void main(void)\n"
1475 "{\n"
1476 "#ifdef USEOFFSETMAPPING\n"
1477 "       // apply offsetmapping\n"
1478 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1479 "#define TexCoord TexCoordOffset\n"
1480 "#endif\n"
1481 "\n"
1482 "       // combine the diffuse textures (base, pants, shirt)\n"
1483 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1484 "#ifdef USEALPHAKILL\n"
1485 "       if (color.a < 0.5)\n"
1486 "               discard;\n"
1487 "#endif\n"
1488 "       color.a *= Alpha;\n"
1489 "#ifdef USECOLORMAPPING\n"
1490 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1491 "#endif\n"
1492 "#ifdef USEVERTEXTEXTUREBLEND\n"
1493 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1494 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1495 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1496 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1497 "       color.a = 1.0;\n"
1498 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1499 "#endif\n"
1500 "\n"
1501 "       // get the surface normal\n"
1502 "#ifdef USEVERTEXTEXTUREBLEND\n"
1503 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1504 "#else\n"
1505 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1506 "#endif\n"
1507 "\n"
1508 "       // get the material colors\n"
1509 "       myhalf3 diffusetex = color.rgb;\n"
1510 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1511 "# ifdef USEVERTEXTEXTUREBLEND\n"
1512 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1513 "# else\n"
1514 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1515 "# endif\n"
1516 "#endif\n"
1517 "\n"
1518 "\n"
1519 "\n"
1520 "\n"
1521 "#ifdef MODE_LIGHTSOURCE\n"
1522 "       // light source\n"
1523 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1524 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1525 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1526 "#ifdef USESPECULAR\n"
1527 "#ifdef USEEXACTSPECULARMATH\n"
1528 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1529 "#else\n"
1530 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1531 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1532 "#endif\n"
1533 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1534 "#endif\n"
1535 "       color.rgb *= LightColor;\n"
1536 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1537 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1538 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1539 "#endif\n"
1540 "# ifdef USECUBEFILTER\n"
1541 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1542 "# endif\n"
1543 "#endif // MODE_LIGHTSOURCE\n"
1544 "\n"
1545 "\n"
1546 "\n"
1547 "\n"
1548 "#ifdef MODE_LIGHTDIRECTION\n"
1549 "#define SHADING\n"
1550 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1551 "#define lightcolor LightColor\n"
1552 "#endif // MODE_LIGHTDIRECTION\n"
1553 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1554 "#define SHADING\n"
1555 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1556 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1557 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1558 "       // convert modelspace light vector to tangentspace\n"
1559 "       myhalf3 lightnormal;\n"
1560 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1561 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1562 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1563 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1564 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1565 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1566 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1567 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1568 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1569 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1570 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1571 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1572 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1573 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1574 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1575 "#define SHADING\n"
1576 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1577 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1578 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1579 "#endif\n"
1580 "\n"
1581 "\n"
1582 "\n"
1583 "\n"
1584 "#ifdef MODE_LIGHTMAP\n"
1585 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1586 "#endif // MODE_LIGHTMAP\n"
1587 "#ifdef MODE_VERTEXCOLOR\n"
1588 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1589 "#endif // MODE_VERTEXCOLOR\n"
1590 "#ifdef MODE_FLATCOLOR\n"
1591 "       color.rgb = diffusetex * Color_Ambient;\n"
1592 "#endif // MODE_FLATCOLOR\n"
1593 "\n"
1594 "\n"
1595 "\n"
1596 "\n"
1597 "#ifdef SHADING\n"
1598 "# ifdef USEDIFFUSE\n"
1599 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1600 "#  ifdef USESPECULAR\n"
1601 "#   ifdef USEEXACTSPECULARMATH\n"
1602 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1603 "#   else\n"
1604 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1605 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1606 "#   endif\n"
1607 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1608 "#  else\n"
1609 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1610 "#  endif\n"
1611 "# else\n"
1612 "       color.rgb = diffusetex * Color_Ambient;\n"
1613 "# endif\n"
1614 "#endif\n"
1615 "\n"
1616 "#ifdef USEDEFERREDLIGHTMAP\n"
1617 "       color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1618 "       color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1619 "#endif\n"
1620 "\n"
1621 "#ifdef USEGLOW\n"
1622 "#ifdef USEVERTEXTEXTUREBLEND\n"
1623 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1624 "#else\n"
1625 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1626 "#endif\n"
1627 "#endif\n"
1628 "\n"
1629 "#ifdef USEFOG\n"
1630 "#ifdef MODE_LIGHTSOURCE\n"
1631 "       color.rgb *= myhalf(FogVertex());\n"
1632 "#else\n"
1633 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1634 "#endif\n"
1635 "#endif\n"
1636 "\n"
1637 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1638 "#ifdef USEREFLECTION\n"
1639 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1640 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1641 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1642 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1643 "       // FIXME temporary hack to detect the case that the reflection\n"
1644 "       // gets blackened at edges due to leaving the area that contains actual\n"
1645 "       // content.\n"
1646 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1647 "       // 'appening.\n"
1648 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1649 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1650 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1651 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1652 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1653 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1654 "#endif\n"
1655 "\n"
1656 "       gl_FragColor = vec4(color);\n"
1657 "}\n"
1658 "#endif // FRAGMENT_SHADER\n"
1659 "\n"
1660 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1661 "#endif // !MODE_DEFERREDGEOMETRY\n"
1662 "#endif // !MODE_WATER\n"
1663 "#endif // !MODE_REFRACTION\n"
1664 "#endif // !MODE_BLOOMBLUR\n"
1665 "#endif // !MODE_GENERIC\n"
1666 "#endif // !MODE_POSTPROCESS\n"
1667 "#endif // !MODE_SHOWDEPTH\n"
1668 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1669 ;
1670
1671 /*
1672 =========================================================================================================================================================
1673
1674
1675
1676 =========================================================================================================================================================
1677
1678
1679
1680 =========================================================================================================================================================
1681
1682
1683
1684 =========================================================================================================================================================
1685
1686
1687
1688 =========================================================================================================================================================
1689
1690
1691
1692 =========================================================================================================================================================
1693
1694
1695
1696 =========================================================================================================================================================
1697 */
1698
1699 const char *builtincgshaderstring =
1700 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1701 "// written by Forest 'LordHavoc' Hale\n"
1702 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1703 "\n"
1704 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1705 "# define USEFOG\n"
1706 "#endif\n"
1707 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1708 "#define USELIGHTMAP\n"
1709 "#endif\n"
1710 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1711 "#define USEEYEVECTOR\n"
1712 "#endif\n"
1713 "\n"
1714 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1715 "#ifdef VERTEX_SHADER\n"
1716 "void main\n"
1717 "(\n"
1718 "float4 gl_Vertex : POSITION,\n"
1719 "uniform float4x4 ModelViewProjectionMatrix,\n"
1720 "out float4 gl_Position : POSITION\n"
1721 ")\n"
1722 "{\n"
1723 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1724 "}\n"
1725 "#endif\n"
1726 "#else // !MODE_DEPTH_ORSHADOW\n"
1727 "\n"
1728 "\n"
1729 "\n"
1730 "\n"
1731 "#ifdef MODE_SHOWDEPTH\n"
1732 "#ifdef VERTEX_SHADER\n"
1733 "void main\n"
1734 "(\n"
1735 "float4 gl_Vertex : POSITION,\n"
1736 "uniform float4x4 ModelViewProjectionMatrix,\n"
1737 "out float4 gl_Position : POSITION,\n"
1738 "out float4 gl_FrontColor : COLOR0\n"
1739 ")\n"
1740 "{\n"
1741 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1742 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1743 "}\n"
1744 "#endif\n"
1745 "\n"
1746 "#ifdef FRAGMENT_SHADER\n"
1747 "void main\n"
1748 "(\n"
1749 "float4 gl_FrontColor : COLOR0,\n"
1750 "out float4 gl_FragColor : COLOR\n"
1751 ")\n"
1752 "{\n"
1753 "       gl_FragColor = gl_FrontColor;\n"
1754 "}\n"
1755 "#endif\n"
1756 "#else // !MODE_SHOWDEPTH\n"
1757 "\n"
1758 "\n"
1759 "\n"
1760 "\n"
1761 "#ifdef MODE_POSTPROCESS\n"
1762 "\n"
1763 "#ifdef VERTEX_SHADER\n"
1764 "void main\n"
1765 "(\n"
1766 "float4 gl_Vertex : POSITION,\n"
1767 "uniform float4x4 ModelViewProjectionMatrix,\n"
1768 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1769 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1770 "out float4 gl_Position : POSITION,\n"
1771 "out float2 TexCoord1 : TEXCOORD0,\n"
1772 "out float2 TexCoord2 : TEXCOORD1\n"
1773 ")\n"
1774 "{\n"
1775 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1776 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1777 "#ifdef USEBLOOM\n"
1778 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1779 "#endif\n"
1780 "}\n"
1781 "#endif\n"
1782 "\n"
1783 "#ifdef FRAGMENT_SHADER\n"
1784 "void main\n"
1785 "(\n"
1786 "float2 TexCoord1 : TEXCOORD0,\n"
1787 "float2 TexCoord2 : TEXCOORD1,\n"
1788 "uniform sampler2D Texture_First,\n"
1789 "#ifdef USEBLOOM\n"
1790 "uniform sampler2D Texture_Second,\n"
1791 "#endif\n"
1792 "#ifdef USEGAMMARAMPS\n"
1793 "uniform sampler2D Texture_GammaRamps,\n"
1794 "#endif\n"
1795 "#ifdef USESATURATION\n"
1796 "uniform float Saturation,\n"
1797 "#endif\n"
1798 "#ifdef USEVIEWTINT\n"
1799 "uniform float4 ViewTintColor,\n"
1800 "#endif\n"
1801 "uniform float4 UserVec1,\n"
1802 "uniform float4 UserVec2,\n"
1803 "uniform float4 UserVec3,\n"
1804 "uniform float4 UserVec4,\n"
1805 "uniform float ClientTime,\n"
1806 "uniform float2 PixelSize,\n"
1807 "out float4 gl_FragColor : COLOR\n"
1808 ")\n"
1809 "{\n"
1810 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1811 "#ifdef USEBLOOM\n"
1812 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1813 "#endif\n"
1814 "#ifdef USEVIEWTINT\n"
1815 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1816 "#endif\n"
1817 "\n"
1818 "#ifdef USEPOSTPROCESSING\n"
1819 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1820 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1821 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1822 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1823 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1824 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1825 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1826 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1827 "#endif\n"
1828 "\n"
1829 "#ifdef USESATURATION\n"
1830 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1831 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1832 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1833 "       gl_FragColor.rgb = mix(float3(y), gl_FragColor.rgb, Saturation);\n"
1834 "#endif\n"
1835 "\n"
1836 "#ifdef USEGAMMARAMPS\n"
1837 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1838 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1839 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1840 "#endif\n"
1841 "}\n"
1842 "#endif\n"
1843 "#else // !MODE_POSTPROCESS\n"
1844 "\n"
1845 "\n"
1846 "\n"
1847 "\n"
1848 "#ifdef MODE_GENERIC\n"
1849 "#ifdef VERTEX_SHADER\n"
1850 "void main\n"
1851 "(\n"
1852 "float4 gl_Vertex : POSITION,\n"
1853 "uniform float4x4 ModelViewProjectionMatrix,\n"
1854 "float4 gl_Color : COLOR0,\n"
1855 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1856 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1857 "out float4 gl_Position : POSITION,\n"
1858 "out float4 gl_FrontColor : COLOR,\n"
1859 "out float2 TexCoord1 : TEXCOORD0,\n"
1860 "out float2 TexCoord2 : TEXCOORD1\n"
1861 ")\n"
1862 "{\n"
1863 "       gl_FrontColor = gl_Color;\n"
1864 "#ifdef USEDIFFUSE\n"
1865 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1866 "#endif\n"
1867 "#ifdef USESPECULAR\n"
1868 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1869 "#endif\n"
1870 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1871 "}\n"
1872 "#endif\n"
1873 "\n"
1874 "#ifdef FRAGMENT_SHADER\n"
1875 "\n"
1876 "void main\n"
1877 "(\n"
1878 "float4 gl_FrontColor : COLOR,\n"
1879 "float2 TexCoord1 : TEXCOORD0,\n"
1880 "float2 TexCoord2 : TEXCOORD1,\n"
1881 "#ifdef USEDIFFUSE\n"
1882 "uniform sampler2D Texture_First,\n"
1883 "#endif\n"
1884 "#ifdef USESPECULAR\n"
1885 "uniform sampler2D Texture_Second,\n"
1886 "#endif\n"
1887 "out float4 gl_FragColor : COLOR\n"
1888 ")\n"
1889 "{\n"
1890 "       gl_FragColor = gl_FrontColor;\n"
1891 "#ifdef USEDIFFUSE\n"
1892 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1893 "#endif\n"
1894 "\n"
1895 "#ifdef USESPECULAR\n"
1896 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1897 "# ifdef USECOLORMAPPING\n"
1898 "       gl_FragColor *= tex2;\n"
1899 "# endif\n"
1900 "# ifdef USEGLOW\n"
1901 "       gl_FragColor += tex2;\n"
1902 "# endif\n"
1903 "# ifdef USEVERTEXTEXTUREBLEND\n"
1904 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
1905 "# endif\n"
1906 "#endif\n"
1907 "}\n"
1908 "#endif\n"
1909 "#else // !MODE_GENERIC\n"
1910 "\n"
1911 "\n"
1912 "\n"
1913 "\n"
1914 "#ifdef MODE_BLOOMBLUR\n"
1915 "#ifdef VERTEX_SHADER\n"
1916 "void main\n"
1917 "(\n"
1918 "float4 gl_Vertex : POSITION,\n"
1919 "uniform float4x4 ModelViewProjectionMatrix,\n"
1920 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1921 "out float4 gl_Position : POSITION,\n"
1922 "out float2 TexCoord : TEXCOORD0\n"
1923 ")\n"
1924 "{\n"
1925 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1926 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1927 "}\n"
1928 "#endif\n"
1929 "\n"
1930 "#ifdef FRAGMENT_SHADER\n"
1931 "\n"
1932 "void main\n"
1933 "(\n"
1934 "float2 TexCoord : TEXCOORD0,\n"
1935 "uniform sampler2D Texture_First,\n"
1936 "uniform float4 BloomBlur_Parameters,\n"
1937 "out float4 gl_FragColor : COLOR\n"
1938 ")\n"
1939 "{\n"
1940 "       int i;\n"
1941 "       float2 tc = TexCoord;\n"
1942 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1943 "       tc += BloomBlur_Parameters.xy;\n"
1944 "       for (i = 1;i < SAMPLES;i++)\n"
1945 "       {\n"
1946 "               color += tex2D(Texture_First, tc).rgb;\n"
1947 "               tc += BloomBlur_Parameters.xy;\n"
1948 "       }\n"
1949 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1950 "}\n"
1951 "#endif\n"
1952 "#else // !MODE_BLOOMBLUR\n"
1953 "#ifdef MODE_REFRACTION\n"
1954 "#ifdef VERTEX_SHADER\n"
1955 "void main\n"
1956 "(\n"
1957 "float4 gl_Vertex : POSITION,\n"
1958 "uniform float4x4 ModelViewProjectionMatrix,\n"
1959 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1960 "uniform mat4 TexMatrix,\n"
1961 "uniform float3 EyePosition,\n"
1962 "out float4 gl_Position : POSITION,\n"
1963 "out float2 TexCoord : TEXCOORD0,\n"
1964 "out float3 EyeVector : TEXCOORD1,\n"
1965 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1966 ")\n"
1967 "{\n"
1968 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1969 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1970 "       ModelViewProjectionPosition = gl_Position;\n"
1971 "}\n"
1972 "#endif\n"
1973 "\n"
1974 "#ifdef FRAGMENT_SHADER\n"
1975 "void main\n"
1976 "(\n"
1977 "float2 TexCoord : TEXCOORD0,\n"
1978 "float3 EyeVector : TEXCOORD1,\n"
1979 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1980 "uniform sampler2D Texture_Normal,\n"
1981 "uniform sampler2D Texture_Refraction,\n"
1982 "uniform sampler2D Texture_Reflection,\n"
1983 "uniform float4 DistortScaleRefractReflect,\n"
1984 "uniform float4 ScreenScaleRefractReflect,\n"
1985 "uniform float4 ScreenCenterRefractReflect,\n"
1986 "uniform float4 RefractColor,\n"
1987 "out float4 gl_FragColor : COLOR\n"
1988 ")\n"
1989 "{\n"
1990 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1991 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1992 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1993 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1994 "       // FIXME temporary hack to detect the case that the reflection\n"
1995 "       // gets blackened at edges due to leaving the area that contains actual\n"
1996 "       // content.\n"
1997 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1998 "       // 'appening.\n"
1999 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2000 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2001 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2002 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2003 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2004 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2005 "}\n"
2006 "#endif\n"
2007 "#else // !MODE_REFRACTION\n"
2008 "\n"
2009 "\n"
2010 "\n"
2011 "\n"
2012 "#ifdef MODE_WATER\n"
2013 "#ifdef VERTEX_SHADER\n"
2014 "\n"
2015 "void main\n"
2016 "(\n"
2017 "float4 gl_Vertex : POSITION,\n"
2018 "uniform float4x4 ModelViewProjectionMatrix,\n"
2019 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2020 "uniform mat4 TexMatrix,\n"
2021 "uniform float3 EyePosition,\n"
2022 "out float4 gl_Position : POSITION,\n"
2023 "out float2 TexCoord : TEXCOORD0,\n"
2024 "out float3 EyeVector : TEXCOORD1,\n"
2025 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2026 ")\n"
2027 "{\n"
2028 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2029 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2030 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2031 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2032 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2033 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2034 "       ModelViewProjectionPosition = gl_Position;\n"
2035 "}\n"
2036 "#endif\n"
2037 "\n"
2038 "#ifdef FRAGMENT_SHADER\n"
2039 "void main\n"
2040 "(\n"
2041 "float2 TexCoord : TEXCOORD0,\n"
2042 "float3 EyeVector : TEXCOORD1,\n"
2043 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2044 "uniform sampler2D Texture_Normal,\n"
2045 "uniform sampler2D Texture_Refraction,\n"
2046 "uniform sampler2D Texture_Reflection,\n"
2047 "uniform float4 DistortScaleRefractReflect,\n"
2048 "uniform float4 ScreenScaleRefractReflect,\n"
2049 "uniform float4 ScreenCenterRefractReflect,\n"
2050 "uniform float4 RefractColor,\n"
2051 "uniform float4 ReflectColor,\n"
2052 "uniform float ReflectFactor,\n"
2053 "uniform float ReflectOffset,\n"
2054 "out float4 gl_FragColor : COLOR\n"
2055 ")\n"
2056 "{\n"
2057 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2058 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2059 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2060 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2061 "       // FIXME temporary hack to detect the case that the reflection\n"
2062 "       // gets blackened at edges due to leaving the area that contains actual\n"
2063 "       // content.\n"
2064 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2065 "       // 'appening.\n"
2066 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2067 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2068 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2069 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2070 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2071 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2072 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2073 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2074 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2075 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2076 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2077 "       gl_FragColor = mix(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2078 "}\n"
2079 "#endif\n"
2080 "#else // !MODE_WATER\n"
2081 "\n"
2082 "\n"
2083 "\n"
2084 "\n"
2085 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2086 "\n"
2087 "// fragment shader specific:\n"
2088 "#ifdef FRAGMENT_SHADER\n"
2089 "\n"
2090 "#ifdef USEFOG\n"
2091 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2092 "{\n"
2093 "       float fogfrac;\n"
2094 "#ifdef USEFOGOUTSIDE\n"
2095 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2096 "#else\n"
2097 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2098 "#endif\n"
2099 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2100 "}\n"
2101 "#endif\n"
2102 "\n"
2103 "#ifdef USEOFFSETMAPPING\n"
2104 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2105 "{\n"
2106 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2107 "       // 14 sample relief mapping: linear search and then binary search\n"
2108 "       // this basically steps forward a small amount repeatedly until it finds\n"
2109 "       // itself inside solid, then jitters forward and back using decreasing\n"
2110 "       // amounts to find the impact\n"
2111 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2112 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2113 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2114 "       float3 RT = float3(TexCoord, 1);\n"
2115 "       OffsetVector *= 0.1;\n"
2116 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2117 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2118 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2119 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2120 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2121 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2122 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2123 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2124 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2125 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2126 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2127 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2128 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2129 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2130 "       return RT.xy;\n"
2131 "#else\n"
2132 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2133 "       // this basically moves forward the full distance, and then backs up based\n"
2134 "       // on height of samples\n"
2135 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2136 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2137 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2138 "       TexCoord += OffsetVector;\n"
2139 "       OffsetVector *= 0.333;\n"
2140 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2141 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2142 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2143 "       return TexCoord;\n"
2144 "#endif\n"
2145 "}\n"
2146 "#endif // USEOFFSETMAPPING\n"
2147 "\n"
2148 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2149 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2150 "# ifndef USESHADOWMAPVSDCT\n"
2151 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2152 "{\n"
2153 "       float3 adir = abs(dir);\n"
2154 "       float2 tc;\n"
2155 "       float2 offset;\n"
2156 "       float ma;\n"
2157 "       if (adir.x > adir.y)\n"
2158 "       {\n"
2159 "               if (adir.x > adir.z) // X\n"
2160 "               {\n"
2161 "                       ma = adir.x;\n"
2162 "                       tc = dir.zy;\n"
2163 "                       offset = float2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2164 "               }\n"
2165 "               else // Z\n"
2166 "               {\n"
2167 "                       ma = adir.z;\n"
2168 "                       tc = dir.xy;\n"
2169 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2170 "               }\n"
2171 "       }\n"
2172 "       else\n"
2173 "       {\n"
2174 "               if (adir.y > adir.z) // Y\n"
2175 "               {\n"
2176 "                       ma = adir.y;\n"
2177 "                       tc = dir.xz;\n"
2178 "                       offset = float2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2179 "               }\n"
2180 "               else // Z\n"
2181 "               {\n"
2182 "                       ma = adir.z;\n"
2183 "                       tc = dir.xy;\n"
2184 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2185 "               }\n"
2186 "       }\n"
2187 "\n"
2188 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2189 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2190 "       stc.z += ShadowMap_Parameters.z;\n"
2191 "       return stc;\n"
2192 "}\n"
2193 "# else\n"
2194 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2195 "{\n"
2196 "       float3 adir = abs(dir);\n"
2197 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2198 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2199 "       float3 stc = float3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2200 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2201 "       stc.z += ShadowMap_Parameters.z;\n"
2202 "       return stc;\n"
2203 "}\n"
2204 "# endif\n"
2205 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2206 "\n"
2207 "#ifdef USESHADOWMAPCUBE\n"
2208 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2209 "{\n"
2210 "    float3 adir = abs(dir);\n"
2211 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2212 "}\n"
2213 "#endif\n"
2214 "\n"
2215 "# ifdef USESHADOWMAPRECT\n"
2216 "#ifdef USESHADOWMAPVSDCT\n"
2217 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2218 "#else\n"
2219 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2220 "#endif\n"
2221 "{\n"
2222 "#ifdef USESHADOWMAPVSDCT\n"
2223 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2224 "#else\n"
2225 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2226 "#endif\n"
2227 "       float f;\n"
2228 "#  ifdef USESHADOWSAMPLER\n"
2229 "\n"
2230 "#    ifdef USESHADOWMAPPCF\n"
2231 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2232 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2233 "#    else\n"
2234 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2235 "#    endif\n"
2236 "\n"
2237 "#  else\n"
2238 "\n"
2239 "#    ifdef USESHADOWMAPPCF\n"
2240 "#      if USESHADOWMAPPCF > 1\n"
2241 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2242 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2243 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2244 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2245 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2246 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2247 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2248 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2249 "#      else\n"
2250 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2251 "    float2 offset = fract(shadowmaptc.xy);\n"
2252 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2253 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2254 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2255 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2256 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2257 "#      endif\n"
2258 "#    else\n"
2259 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2260 "#    endif\n"
2261 "\n"
2262 "#  endif\n"
2263 "       return f;\n"
2264 "}\n"
2265 "# endif\n"
2266 "\n"
2267 "# ifdef USESHADOWMAP2D\n"
2268 "#ifdef USESHADOWMAPVSDCT\n"
2269 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2270 "#else\n"
2271 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2272 "#endif\n"
2273 "{\n"
2274 "#ifdef USESHADOWMAPVSDCT\n"
2275 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2276 "#else\n"
2277 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2278 "#endif\n"
2279 "    float f;\n"
2280 "\n"
2281 "#  ifdef USESHADOWSAMPLER\n"
2282 "#    ifdef USESHADOWMAPPCF\n"
2283 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2284 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2285 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2286 "#    else\n"
2287 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2288 "#    endif\n"
2289 "#  else\n"
2290 "#    ifdef USESHADOWMAPPCF\n"
2291 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2292 "#      ifdef GL_ARB_texture_gather\n"
2293 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2294 "#      else\n"
2295 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2296 "#      endif\n"
2297 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2298 "    center *= ShadowMap_TextureScale;\n"
2299 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2300 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2301 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2302 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2303 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2304 "                mix(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2305 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2306 "#     else\n"
2307 "#      ifdef GL_EXT_gpu_shader4\n"
2308 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, ifloat2(x, y)).r\n"
2309 "#      else\n"
2310 "#        define texval(x, y) tex2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2311 "#      endif\n"
2312 "#      if USESHADOWMAPPCF > 1\n"
2313 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2314 "    center *= ShadowMap_TextureScale;\n"
2315 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2316 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2317 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2318 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2319 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2320 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2321 "#      else\n"
2322 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
2323 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2324 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2325 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2326 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2327 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2328 "#      endif\n"
2329 "#     endif\n"
2330 "#    else\n"
2331 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2332 "#    endif\n"
2333 "#  endif\n"
2334 "    return f;\n"
2335 "}\n"
2336 "# endif\n"
2337 "\n"
2338 "# ifdef USESHADOWMAPCUBE\n"
2339 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2340 "{\n"
2341 "    // apply depth texture cubemap as light filter\n"
2342 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2343 "    float f;\n"
2344 "#  ifdef USESHADOWSAMPLER\n"
2345 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2346 "#  else\n"
2347 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2348 "#  endif\n"
2349 "    return f;\n"
2350 "}\n"
2351 "# endif\n"
2352 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2353 "#endif // FRAGMENT_SHADER\n"
2354 "\n"
2355 "\n"
2356 "\n"
2357 "\n"
2358 "#ifdef MODE_DEFERREDGEOMETRY\n"
2359 "#ifdef VERTEX_SHADER\n"
2360 "void main\n"
2361 "(\n"
2362 "float4 gl_Vertex : POSITION,\n"
2363 "uniform float4x4 ModelViewProjectionMatrix,\n"
2364 "#ifdef USEVERTEXTEXTUREBLEND\n"
2365 "float4 gl_Color : COLOR0,\n"
2366 "#endif\n"
2367 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2368 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2369 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2370 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2371 "uniform mat4 TexMatrix,\n"
2372 "#ifdef USEVERTEXTEXTUREBLEND\n"
2373 "uniform mat4 BackgroundTexMatrix,\n"
2374 "#endif\n"
2375 "uniform mat4 ModelViewMatrix,\n"
2376 "out float4 gl_Position : POSITION,\n"
2377 "out float4 gl_FrontColor : COLOR,\n"
2378 "out float4 TexCoordBoth : TEXCOORD0,\n"
2379 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2380 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2381 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2382 ")\n"
2383 "{\n"
2384 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2385 "#ifdef USEVERTEXTEXTUREBLEND\n"
2386 "       gl_FrontColor = gl_Color;\n"
2387 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2388 "#endif\n"
2389 "\n"
2390 "       // transform unnormalized eye direction into tangent space\n"
2391 "#ifdef USEOFFSETMAPPING\n"
2392 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2393 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2394 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2395 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2396 "#endif\n"
2397 "\n"
2398 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2399 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2400 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2401 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2402 "}\n"
2403 "#endif // VERTEX_SHADER\n"
2404 "\n"
2405 "#ifdef FRAGMENT_SHADER\n"
2406 "void main\n"
2407 "(\n"
2408 "float4 TexCoordBoth : TEXCOORD0,\n"
2409 "float3 EyeVector : TEXCOORD2,\n"
2410 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2411 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2412 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2413 "uniform sampler2D Texture_Normal,\n"
2414 "#ifdef USEALPHAKILL\n"
2415 "uniform sampler2D Texture_Color,\n"
2416 "#endif\n"
2417 "#ifdef USEVERTEXTEXTUREBLEND\n"
2418 "uniform sampler2D Texture_SecondaryNormal,\n"
2419 "#endif\n"
2420 "#ifdef USEOFFSETMAPPING\n"
2421 "uniform float OffsetMapping_Scale,\n"
2422 "#endif\n"
2423 "uniform half SpecularPower,\n"
2424 "out float4 gl_FragColor : COLOR\n"
2425 ")\n"
2426 "{\n"
2427 "       float2 TexCoord = TexCoordBoth.xy;\n"
2428 "#ifdef USEOFFSETMAPPING\n"
2429 "       // apply offsetmapping\n"
2430 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2431 "#define TexCoord TexCoordOffset\n"
2432 "#endif\n"
2433 "\n"
2434 "#ifdef USEALPHAKILL\n"
2435 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2436 "               discard;\n"
2437 "#endif\n"
2438 "\n"
2439 "#ifdef USEVERTEXTEXTUREBLEND\n"
2440 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2441 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2442 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2443 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2444 "#endif\n"
2445 "\n"
2446 "#ifdef USEVERTEXTEXTUREBLEND\n"
2447 "       float3 surfacenormal = mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2448 "#else\n"
2449 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2450 "#endif\n"
2451 "\n"
2452 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2453 "}\n"
2454 "#endif // FRAGMENT_SHADER\n"
2455 "#else // !MODE_DEFERREDGEOMETRY\n"
2456 "\n"
2457 "\n"
2458 "\n"
2459 "\n"
2460 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2461 "#ifdef VERTEX_SHADER\n"
2462 "void main\n"
2463 "(\n"
2464 "float4 gl_Vertex : POSITION,\n"
2465 "uniform float4x4 ModelViewProjectionMatrix,\n"
2466 "uniform mat4 ModelViewMatrix,\n"
2467 "out float4 gl_Position : POSITION,\n"
2468 "out float4 ModelViewPosition : TEXCOORD0\n"
2469 ")\n"
2470 "{\n"
2471 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2472 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2473 "}\n"
2474 "#endif // VERTEX_SHADER\n"
2475 "\n"
2476 "#ifdef FRAGMENT_SHADER\n"
2477 "void main\n"
2478 "(\n"
2479 "float2 Pixel : WPOS,\n"
2480 "float4 ModelViewPosition : TEXCOORD0,\n"
2481 "uniform mat4 ViewToLight,\n"
2482 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2483 "uniform float3 LightPosition,\n"
2484 "uniform half3 DeferredColor_Ambient,\n"
2485 "uniform half3 DeferredColor_Diffuse,\n"
2486 "#ifdef USESPECULAR\n"
2487 "uniform half3 DeferredColor_Specular,\n"
2488 "uniform half SpecularPower,\n"
2489 "#endif\n"
2490 "uniform sampler2D Texture_Attenuation,\n"
2491 "uniform samplerRECT Texture_ScreenDepth,\n"
2492 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2493 "\n"
2494 "#ifdef USESHADOWMAPRECT\n"
2495 "# ifdef USESHADOWSAMPLER\n"
2496 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2497 "# else\n"
2498 "uniform samplerRECT Texture_ShadowMapRect,\n"
2499 "# endif\n"
2500 "#endif\n"
2501 "\n"
2502 "#ifdef USESHADOWMAP2D\n"
2503 "# ifdef USESHADOWSAMPLER\n"
2504 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2505 "# else\n"
2506 "uniform sampler2D Texture_ShadowMap2D,\n"
2507 "# endif\n"
2508 "#endif\n"
2509 "\n"
2510 "#ifdef USESHADOWMAPVSDCT\n"
2511 "uniform samplerCUBE Texture_CubeProjection,\n"
2512 "#endif\n"
2513 "\n"
2514 "#ifdef USESHADOWMAPCUBE\n"
2515 "# ifdef USESHADOWSAMPLER\n"
2516 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2517 "# else\n"
2518 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2519 "# endif\n"
2520 "#endif\n"
2521 "\n"
2522 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2523 "uniform float2 ShadowMap_TextureScale,\n"
2524 "uniform float4 ShadowMap_Parameters,\n"
2525 "#endif\n"
2526 "\n"
2527 "out float4 gl_FragData0 : COLOR0,\n"
2528 "out float4 gl_FragData1 : COLOR1\n"
2529 ")\n"
2530 "{\n"
2531 "       // calculate viewspace pixel position\n"
2532 "       float3 position;\n"
2533 "       position.z = ScreenToDepth.y / (texRECT(Texture_ScreenDepth, Pixel).r + ScreenToDepth.x);\n"
2534 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2535 "       // decode viewspace pixel normal\n"
2536 "       half4 normalmap = texRECT(Texture_ScreenNormalMap, Pixel);\n"
2537 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2538 "       // surfacenormal = pixel normal in viewspace\n"
2539 "       // LightVector = pixel to light in viewspace\n"
2540 "       // CubeVector = position in lightspace\n"
2541 "       // eyevector = pixel to view in viewspace\n"
2542 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2543 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2544 "#ifdef USEDIFFUSE\n"
2545 "       // calculate diffuse shading\n"
2546 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2547 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2548 "#endif\n"
2549 "#ifdef USESPECULAR\n"
2550 "       // calculate directional shading\n"
2551 "       float3 eyevector = position * -1.0;\n"
2552 "#  ifdef USEEXACTSPECULARMATH\n"
2553 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2554 "#  else\n"
2555 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2556 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2557 "#  endif\n"
2558 "#endif\n"
2559 "\n"
2560 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2561 "       fade *= ShadowMapCompare(CubeVector,\n"
2562 "# if defined(USESHADOWMAP2D)\n"
2563 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2564 "# endif\n"
2565 "# if defined(USESHADOWMAPRECT)\n"
2566 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2567 "# endif\n"
2568 "# if defined(USESHADOWMAPCUBE)\n"
2569 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2570 "# endif\n"
2571 "\n"
2572 "#ifdef USESHADOWMAPVSDCT\n"
2573 ", Texture_CubeProjection\n"
2574 "#endif\n"
2575 "       );\n"
2576 "#endif\n"
2577 "\n"
2578 "#ifdef USEDIFFUSE\n"
2579 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2580 "#else\n"
2581 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2582 "#endif\n"
2583 "#ifdef USESPECULAR\n"
2584 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2585 "#else\n"
2586 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2587 "#endif\n"
2588 "\n"
2589 "# ifdef USECUBEFILTER\n"
2590 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2591 "       gl_FragData0 *= cubecolor;\n"
2592 "       gl_FragData1 *= cubecolor;\n"
2593 "# endif\n"
2594 "}\n"
2595 "#endif // FRAGMENT_SHADER\n"
2596 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2597 "\n"
2598 "\n"
2599 "\n"
2600 "\n"
2601 "#ifdef VERTEX_SHADER\n"
2602 "void main\n"
2603 "(\n"
2604 "float4 gl_Vertex : POSITION,\n"
2605 "uniform float4x4 ModelViewProjectionMatrix,\n"
2606 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2607 "float4 gl_Color : COLOR0,\n"
2608 "#endif\n"
2609 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2610 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2611 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2612 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2613 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2614 "\n"
2615 "uniform float3 EyePosition,\n"
2616 "uniform mat4 TexMatrix,\n"
2617 "#ifdef USEVERTEXTEXTUREBLEND\n"
2618 "uniform mat4 BackgroundTexMatrix,\n"
2619 "#endif\n"
2620 "#ifdef MODE_LIGHTSOURCE\n"
2621 "uniform mat4 ModelToLight,\n"
2622 "#endif\n"
2623 "#ifdef MODE_LIGHTSOURCE\n"
2624 "uniform float3 LightPosition,\n"
2625 "#endif\n"
2626 "#ifdef MODE_LIGHTDIRECTION\n"
2627 "uniform float3 LightDir,\n"
2628 "#endif\n"
2629 "uniform float4 FogPlane,\n"
2630 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2631 "uniform float3 LightPosition,\n"
2632 "#endif\n"
2633 "\n"
2634 "out float4 gl_FrontColor : COLOR,\n"
2635 "out float4 TexCoordBoth : TEXCOORD0,\n"
2636 "#ifdef USELIGHTMAP\n"
2637 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2638 "#endif\n"
2639 "#ifdef USEEYEVECTOR\n"
2640 "out float3 EyeVector : TEXCOORD2,\n"
2641 "#endif\n"
2642 "#ifdef USEREFLECTION\n"
2643 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2644 "#endif\n"
2645 "#ifdef USEFOG\n"
2646 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2647 "#endif\n"
2648 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2649 "out float3 LightVector : TEXCOORD5,\n"
2650 "#endif\n"
2651 "#ifdef MODE_LIGHTSOURCE\n"
2652 "out float3 CubeVector : TEXCOORD3,\n"
2653 "#endif\n"
2654 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2655 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2656 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2657 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2658 "#endif\n"
2659 "out float4 gl_Position : POSITION\n"
2660 ")\n"
2661 "{\n"
2662 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2663 "       gl_FrontColor = gl_Color;\n"
2664 "#endif\n"
2665 "       // copy the surface texcoord\n"
2666 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2667 "#ifdef USEVERTEXTEXTUREBLEND\n"
2668 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2669 "#endif\n"
2670 "#ifdef USELIGHTMAP\n"
2671 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2672 "#endif\n"
2673 "\n"
2674 "#ifdef MODE_LIGHTSOURCE\n"
2675 "       // transform vertex position into light attenuation/cubemap space\n"
2676 "       // (-1 to +1 across the light box)\n"
2677 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2678 "\n"
2679 "# ifdef USEDIFFUSE\n"
2680 "       // transform unnormalized light direction into tangent space\n"
2681 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2682 "       //  normalize it per pixel)\n"
2683 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2684 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2685 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2686 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2687 "# endif\n"
2688 "#endif\n"
2689 "\n"
2690 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2691 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2692 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2693 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2694 "#endif\n"
2695 "\n"
2696 "       // transform unnormalized eye direction into tangent space\n"
2697 "#ifdef USEEYEVECTOR\n"
2698 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2699 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2700 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2701 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2702 "#endif\n"
2703 "\n"
2704 "#ifdef USEFOG\n"
2705 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2706 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2710 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2711 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2712 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2713 "#endif\n"
2714 "\n"
2715 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2716 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2717 "\n"
2718 "#ifdef USEREFLECTION\n"
2719 "       ModelViewProjectionPosition = gl_Position;\n"
2720 "#endif\n"
2721 "}\n"
2722 "#endif // VERTEX_SHADER\n"
2723 "\n"
2724 "\n"
2725 "\n"
2726 "\n"
2727 "#ifdef FRAGMENT_SHADER\n"
2728 "void main\n"
2729 "(\n"
2730 "#ifdef USEDEFERREDLIGHTMAP\n"
2731 "float2 Pixel : WPOS,\n"
2732 "#endif\n"
2733 "float4 gl_FrontColor : COLOR,\n"
2734 "float4 TexCoordBoth : TEXCOORD0,\n"
2735 "#ifdef USELIGHTMAP\n"
2736 "float2 TexCoordLightmap : TEXCOORD1,\n"
2737 "#endif\n"
2738 "#ifdef USEEYEVECTOR\n"
2739 "float3 EyeVector : TEXCOORD2,\n"
2740 "#endif\n"
2741 "#ifdef USEREFLECTION\n"
2742 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2743 "#endif\n"
2744 "#ifdef USEFOG\n"
2745 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2746 "#endif\n"
2747 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2748 "float3 LightVector : TEXCOORD5,\n"
2749 "#endif\n"
2750 "#ifdef MODE_LIGHTSOURCE\n"
2751 "float3 CubeVector : TEXCOORD3,\n"
2752 "#endif\n"
2753 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2754 "float4 ModelViewPosition : TEXCOORD0,\n"
2755 "#endif\n"
2756 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2757 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2758 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2759 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2760 "#endif\n"
2761 "\n"
2762 "uniform sampler2D Texture_Normal,\n"
2763 "uniform sampler2D Texture_Color,\n"
2764 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2765 "uniform sampler2D Texture_Gloss,\n"
2766 "#endif\n"
2767 "#ifdef USEGLOW\n"
2768 "uniform sampler2D Texture_Glow,\n"
2769 "#endif\n"
2770 "#ifdef USEVERTEXTEXTUREBLEND\n"
2771 "uniform sampler2D Texture_SecondaryNormal,\n"
2772 "uniform sampler2D Texture_SecondaryColor,\n"
2773 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2774 "uniform sampler2D Texture_SecondaryGloss,\n"
2775 "#endif\n"
2776 "#ifdef USEGLOW\n"
2777 "uniform sampler2D Texture_SecondaryGlow,\n"
2778 "#endif\n"
2779 "#endif\n"
2780 "#ifdef USECOLORMAPPING\n"
2781 "uniform sampler2D Texture_Pants,\n"
2782 "uniform sampler2D Texture_Shirt,\n"
2783 "#endif\n"
2784 "#ifdef USEFOG\n"
2785 "uniform sampler2D Texture_FogMask,\n"
2786 "#endif\n"
2787 "#ifdef USELIGHTMAP\n"
2788 "uniform sampler2D Texture_Lightmap,\n"
2789 "#endif\n"
2790 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2791 "uniform sampler2D Texture_Deluxemap,\n"
2792 "#endif\n"
2793 "#ifdef USEREFLECTION\n"
2794 "uniform sampler2D Texture_Reflection,\n"
2795 "#endif\n"
2796 "\n"
2797 "//#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2798 "uniform samplerRECT Texture_ScreenDepth,\n"
2799 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2800 "//#endif\n"
2801 "#ifdef USEDEFERREDLIGHTMAP\n"
2802 "uniform samplerRECT Texture_ScreenDiffuse,\n"
2803 "uniform samplerRECT Texture_ScreenSpecular,\n"
2804 "#endif\n"
2805 "\n"
2806 "#ifdef USECOLORMAPPING\n"
2807 "uniform half3 Color_Pants,\n"
2808 "uniform half3 Color_Shirt,\n"
2809 "#endif\n"
2810 "#ifdef USEFOG\n"
2811 "uniform float3 FogColor,\n"
2812 "uniform float FogRangeRecip,\n"
2813 "uniform float FogPlaneViewDist,\n"
2814 "uniform float FogHeightFade,\n"
2815 "#endif\n"
2816 "\n"
2817 "#ifdef USEOFFSETMAPPING\n"
2818 "uniform float OffsetMapping_Scale,\n"
2819 "#endif\n"
2820 "\n"
2821 "#ifdef USEDEFERREDLIGHTMAP\n"
2822 "uniform half3 DeferredMod_Diffuse,\n"
2823 "uniform half3 DeferredMod_Specular,\n"
2824 "#endif\n"
2825 "uniform half3 Color_Ambient,\n"
2826 "uniform half3 Color_Diffuse,\n"
2827 "uniform half3 Color_Specular,\n"
2828 "uniform half SpecularPower,\n"
2829 "#ifdef USEGLOW\n"
2830 "uniform half3 Color_Glow,\n"
2831 "#endif\n"
2832 "uniform half Alpha,\n"
2833 "#ifdef USEREFLECTION\n"
2834 "uniform float4 DistortScaleRefractReflect,\n"
2835 "uniform float4 ScreenScaleRefractReflect,\n"
2836 "uniform float4 ScreenCenterRefractReflect,\n"
2837 "uniform half4 ReflectColor,\n"
2838 "#endif\n"
2839 "#ifdef MODE_LIGHTDIRECTION\n"
2840 "uniform half3 LightColor,\n"
2841 "#endif\n"
2842 "#ifdef MODE_LIGHTSOURCE\n"
2843 "uniform half3 LightColor,\n"
2844 "#endif\n"
2845 "\n"
2846 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2847 "uniform sampler2D Texture_Attenuation,\n"
2848 "uniform samplerCUBE Texture_Cube,\n"
2849 "\n"
2850 "#ifdef USESHADOWMAPRECT\n"
2851 "# ifdef USESHADOWSAMPLER\n"
2852 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2853 "# else\n"
2854 "uniform samplerRECT Texture_ShadowMapRect,\n"
2855 "# endif\n"
2856 "#endif\n"
2857 "\n"
2858 "#ifdef USESHADOWMAP2D\n"
2859 "# ifdef USESHADOWSAMPLER\n"
2860 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2861 "# else\n"
2862 "uniform sampler2D Texture_ShadowMap2D,\n"
2863 "# endif\n"
2864 "#endif\n"
2865 "\n"
2866 "#ifdef USESHADOWMAPVSDCT\n"
2867 "uniform samplerCUBE Texture_CubeProjection,\n"
2868 "#endif\n"
2869 "\n"
2870 "#ifdef USESHADOWMAPCUBE\n"
2871 "# ifdef USESHADOWSAMPLER\n"
2872 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2873 "# else\n"
2874 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2875 "# endif\n"
2876 "#endif\n"
2877 "\n"
2878 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2879 "uniform float2 ShadowMap_TextureScale,\n"
2880 "uniform float4 ShadowMap_Parameters,\n"
2881 "#endif\n"
2882 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2883 "\n"
2884 "out float4 gl_FragColor : COLOR\n"
2885 ")\n"
2886 "{\n"
2887 "       float2 TexCoord = TexCoordBoth.xy;\n"
2888 "#ifdef USEVERTEXTEXTUREBLEND\n"
2889 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2890 "#endif\n"
2891 "#ifdef USEOFFSETMAPPING\n"
2892 "       // apply offsetmapping\n"
2893 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2894 "#define TexCoord TexCoordOffset\n"
2895 "#endif\n"
2896 "\n"
2897 "       // combine the diffuse textures (base, pants, shirt)\n"
2898 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2899 "#ifdef USEALPHAKILL\n"
2900 "       if (color.a < 0.5)\n"
2901 "               discard;\n"
2902 "#endif\n"
2903 "       color.a *= Alpha;\n"
2904 "#ifdef USECOLORMAPPING\n"
2905 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2906 "#endif\n"
2907 "#ifdef USEVERTEXTEXTUREBLEND\n"
2908 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2909 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2910 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2911 "       color.rgb = half3(mix(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2912 "       color.a = 1.0;\n"
2913 "       //color = mix(half4(1, 0, 0, 1), color, terrainblend);\n"
2914 "#endif\n"
2915 "\n"
2916 "       // get the surface normal\n"
2917 "#ifdef USEVERTEXTEXTUREBLEND\n"
2918 "       half3 surfacenormal = normalize(half3(mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2919 "#else\n"
2920 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2921 "#endif\n"
2922 "\n"
2923 "       // get the material colors\n"
2924 "       half3 diffusetex = color.rgb;\n"
2925 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2926 "# ifdef USEVERTEXTEXTUREBLEND\n"
2927 "       half3 glosstex = half3(mix(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2928 "# else\n"
2929 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2930 "# endif\n"
2931 "#endif\n"
2932 "\n"
2933 "\n"
2934 "\n"
2935 "\n"
2936 "#ifdef MODE_LIGHTSOURCE\n"
2937 "       // light source\n"
2938 "       half3 lightnormal = half3(normalize(LightVector));\n"
2939 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2940 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2941 "#ifdef USESPECULAR\n"
2942 "#ifdef USEEXACTSPECULARMATH\n"
2943 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2944 "#else\n"
2945 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2946 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2947 "#endif\n"
2948 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2949 "#endif\n"
2950 "       color.rgb *= LightColor;\n"
2951 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2952 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2953 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2954 "# if defined(USESHADOWMAP2D)\n"
2955 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2956 "# endif\n"
2957 "# if defined(USESHADOWMAPRECT)\n"
2958 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2959 "# endif\n"
2960 "# if defined(USESHADOWMAPCUBE)\n"
2961 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2962 "# endif\n"
2963 "\n"
2964 "#ifdef USESHADOWMAPVSDCT\n"
2965 ", Texture_CubeProjection\n"
2966 "#endif\n"
2967 "       );\n"
2968 "\n"
2969 "#endif\n"
2970 "# ifdef USECUBEFILTER\n"
2971 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2972 "# endif\n"
2973 "#endif // MODE_LIGHTSOURCE\n"
2974 "\n"
2975 "\n"
2976 "\n"
2977 "\n"
2978 "#ifdef MODE_LIGHTDIRECTION\n"
2979 "#define SHADING\n"
2980 "       half3 lightnormal = half3(normalize(LightVector));\n"
2981 "#define lightcolor LightColor\n"
2982 "#endif // MODE_LIGHTDIRECTION\n"
2983 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2984 "#define SHADING\n"
2985 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
2986 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
2987 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
2988 "       // convert modelspace light vector to tangentspace\n"
2989 "       half3 lightnormal;\n"
2990 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
2991 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
2992 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
2993 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
2994 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
2995 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
2996 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
2997 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
2998 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
2999 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3000 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3001 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3002 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3003 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3004 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3005 "#define SHADING\n"
3006 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3007 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3008 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3009 "#endif\n"
3010 "\n"
3011 "\n"
3012 "\n"
3013 "\n"
3014 "#ifdef MODE_LIGHTMAP\n"
3015 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3016 "#endif // MODE_LIGHTMAP\n"
3017 "#ifdef MODE_VERTEXCOLOR\n"
3018 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3019 "#endif // MODE_VERTEXCOLOR\n"
3020 "#ifdef MODE_FLATCOLOR\n"
3021 "       color.rgb = diffusetex * Color_Ambient;\n"
3022 "#endif // MODE_FLATCOLOR\n"
3023 "\n"
3024 "\n"
3025 "\n"
3026 "\n"
3027 "#ifdef SHADING\n"
3028 "# ifdef USEDIFFUSE\n"
3029 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3030 "#  ifdef USESPECULAR\n"
3031 "#   ifdef USEEXACTSPECULARMATH\n"
3032 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3033 "#   else\n"
3034 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3035 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3036 "#   endif\n"
3037 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3038 "#  else\n"
3039 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3040 "#  endif\n"
3041 "# else\n"
3042 "       color.rgb = diffusetex * Color_Ambient;\n"
3043 "# endif\n"
3044 "#endif\n"
3045 "\n"
3046 "#ifdef USEDEFERREDLIGHTMAP\n"
3047 "       color.rgb += diffusetex * half3(texRECT(Texture_ScreenDiffuse, Pixel)) * DeferredMod_Diffuse;\n"
3048 "       color.rgb += glosstex * half3(texRECT(Texture_ScreenSpecular, Pixel)) * DeferredMod_Specular;\n"
3049 "       color.rgb = half3(texRECT(Texture_ScreenDepth, Pixel));\n"
3050 "#endif\n"
3051 "\n"
3052 "#ifdef USEGLOW\n"
3053 "#ifdef USEVERTEXTEXTUREBLEND\n"
3054 "       color.rgb += mix(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3055 "#else\n"
3056 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3057 "#endif\n"
3058 "#endif\n"
3059 "\n"
3060 "#ifdef USEFOG\n"
3061 "#ifdef MODE_LIGHTSOURCE\n"
3062 "       color.rgb *= half(FogVertex());\n"
3063 "#else\n"
3064 "       color.rgb = mix(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3065 "#endif\n"
3066 "#endif\n"
3067 "\n"
3068 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3069 "#ifdef USEREFLECTION\n"
3070 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3071 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3072 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3073 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3074 "       // FIXME temporary hack to detect the case that the reflection\n"
3075 "       // gets blackened at edges due to leaving the area that contains actual\n"
3076 "       // content.\n"
3077 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3078 "       // 'appening.\n"
3079 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3080 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3081 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3082 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3083 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3084 "       color.rgb = mix(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3085 "#endif\n"
3086 "\n"
3087 "       gl_FragColor = float4(color);\n"
3088 "}\n"
3089 "#endif // FRAGMENT_SHADER\n"
3090 "\n"
3091 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3092 "#endif // !MODE_DEFERREDGEOMETRY\n"
3093 "#endif // !MODE_WATER\n"
3094 "#endif // !MODE_REFRACTION\n"
3095 "#endif // !MODE_BLOOMBLUR\n"
3096 "#endif // !MODE_GENERIC\n"
3097 "#endif // !MODE_POSTPROCESS\n"
3098 "#endif // !MODE_SHOWDEPTH\n"
3099 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3100 ;
3101
3102 //=======================================================================================================================================================
3103
3104 typedef struct shaderpermutationinfo_s
3105 {
3106         const char *pretext;
3107         const char *name;
3108 }
3109 shaderpermutationinfo_t;
3110
3111 typedef struct shadermodeinfo_s
3112 {
3113         const char *vertexfilename;
3114         const char *geometryfilename;
3115         const char *fragmentfilename;
3116         const char *pretext;
3117         const char *name;
3118 }
3119 shadermodeinfo_t;
3120
3121 typedef enum shaderpermutation_e
3122 {
3123         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3124         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3125         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3126         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3127         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3128         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3129         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3130         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3131         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3132         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3133         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3134         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3135         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3136         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3137         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3138         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3139         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3140         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3141         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3142         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3143         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3144         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3145         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3146         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3147         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3148         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3149         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3150         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3151 }
3152 shaderpermutation_t;
3153
3154 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3155 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3156 {
3157         {"#define USEDIFFUSE\n", " diffuse"},
3158         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3159         {"#define USEVIEWTINT\n", " viewtint"},
3160         {"#define USECOLORMAPPING\n", " colormapping"},
3161         {"#define USESATURATION\n", " saturation"},
3162         {"#define USEFOGINSIDE\n", " foginside"},
3163         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3164         {"#define USEGAMMARAMPS\n", " gammaramps"},
3165         {"#define USECUBEFILTER\n", " cubefilter"},
3166         {"#define USEGLOW\n", " glow"},
3167         {"#define USEBLOOM\n", " bloom"},
3168         {"#define USESPECULAR\n", " specular"},
3169         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3170         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3171         {"#define USEREFLECTION\n", " reflection"},
3172         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3173         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3174         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3175         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3176         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3177         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3178         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3179         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3180         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3181         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3182         {"#define USEALPHAKILL\n", " alphakill"},
3183 };
3184
3185 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3186 typedef enum shadermode_e
3187 {
3188         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3189         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3190         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3191         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3192         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3193         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3194         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3195         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3196         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3197         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3198         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3199         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3200         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3201         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3202         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3203         SHADERMODE_COUNT
3204 }
3205 shadermode_t;
3206
3207 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3208 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3209 {
3210         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3211         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3212         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3213         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3214         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3215         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3216         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3217         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3218         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3219         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3220         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3221         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3222         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3223         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3224         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3225 };
3226
3227 #ifdef SUPPORTCG
3228 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3229 {
3230         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3231         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3232         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3233         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3234         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3235         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3236         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3237         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3238         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3239         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3240         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3241         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3242         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3243         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3244         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3245 };
3246 #endif
3247
3248 struct r_glsl_permutation_s;
3249 typedef struct r_glsl_permutation_s
3250 {
3251         /// hash lookup data
3252         struct r_glsl_permutation_s *hashnext;
3253         unsigned int mode;
3254         unsigned int permutation;
3255
3256         /// indicates if we have tried compiling this permutation already
3257         qboolean compiled;
3258         /// 0 if compilation failed
3259         int program;
3260         /// locations of detected uniforms in program object, or -1 if not found
3261         int loc_Texture_First;
3262         int loc_Texture_Second;
3263         int loc_Texture_GammaRamps;
3264         int loc_Texture_Normal;
3265         int loc_Texture_Color;
3266         int loc_Texture_Gloss;
3267         int loc_Texture_Glow;
3268         int loc_Texture_SecondaryNormal;
3269         int loc_Texture_SecondaryColor;
3270         int loc_Texture_SecondaryGloss;
3271         int loc_Texture_SecondaryGlow;
3272         int loc_Texture_Pants;
3273         int loc_Texture_Shirt;
3274         int loc_Texture_FogMask;
3275         int loc_Texture_Lightmap;
3276         int loc_Texture_Deluxemap;
3277         int loc_Texture_Attenuation;
3278         int loc_Texture_Cube;
3279         int loc_Texture_Refraction;
3280         int loc_Texture_Reflection;
3281         int loc_Texture_ShadowMapRect;
3282         int loc_Texture_ShadowMapCube;
3283         int loc_Texture_ShadowMap2D;
3284         int loc_Texture_CubeProjection;
3285         int loc_Texture_ScreenDepth;
3286         int loc_Texture_ScreenNormalMap;
3287         int loc_Texture_ScreenDiffuse;
3288         int loc_Texture_ScreenSpecular;
3289         int loc_Alpha;
3290         int loc_BloomBlur_Parameters;
3291         int loc_ClientTime;
3292         int loc_Color_Ambient;
3293         int loc_Color_Diffuse;
3294         int loc_Color_Specular;
3295         int loc_Color_Glow;
3296         int loc_Color_Pants;
3297         int loc_Color_Shirt;
3298         int loc_DeferredColor_Ambient;
3299         int loc_DeferredColor_Diffuse;
3300         int loc_DeferredColor_Specular;
3301         int loc_DeferredMod_Diffuse;
3302         int loc_DeferredMod_Specular;
3303         int loc_DistortScaleRefractReflect;
3304         int loc_EyePosition;
3305         int loc_FogColor;
3306         int loc_FogHeightFade;
3307         int loc_FogPlane;
3308         int loc_FogPlaneViewDist;
3309         int loc_FogRangeRecip;
3310         int loc_LightColor;
3311         int loc_LightDir;
3312         int loc_LightPosition;
3313         int loc_OffsetMapping_Scale;
3314         int loc_PixelSize;
3315         int loc_ReflectColor;
3316         int loc_ReflectFactor;
3317         int loc_ReflectOffset;
3318         int loc_RefractColor;
3319         int loc_Saturation;
3320         int loc_ScreenCenterRefractReflect;
3321         int loc_ScreenScaleRefractReflect;
3322         int loc_ScreenToDepth;
3323         int loc_ShadowMap_Parameters;
3324         int loc_ShadowMap_TextureScale;
3325         int loc_SpecularPower;
3326         int loc_UserVec1;
3327         int loc_UserVec2;
3328         int loc_UserVec3;
3329         int loc_UserVec4;
3330         int loc_ViewTintColor;
3331         int loc_ViewToLight;
3332         int loc_ModelToLight;
3333         int loc_TexMatrix;
3334         int loc_BackgroundTexMatrix;
3335         int loc_ModelViewProjectionMatrix;
3336         int loc_ModelViewMatrix;
3337 }
3338 r_glsl_permutation_t;
3339
3340 #define SHADERPERMUTATION_HASHSIZE 256
3341
3342 /// information about each possible shader permutation
3343 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3344 /// currently selected permutation
3345 r_glsl_permutation_t *r_glsl_permutation;
3346 /// storage for permutations linked in the hash table
3347 memexpandablearray_t r_glsl_permutationarray;
3348
3349 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3350 {
3351         //unsigned int hashdepth = 0;
3352         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3353         r_glsl_permutation_t *p;
3354         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3355         {
3356                 if (p->mode == mode && p->permutation == permutation)
3357                 {
3358                         //if (hashdepth > 10)
3359                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3360                         return p;
3361                 }
3362                 //hashdepth++;
3363         }
3364         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3365         p->mode = mode;
3366         p->permutation = permutation;
3367         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3368         r_glsl_permutationhash[mode][hashindex] = p;
3369         //if (hashdepth > 10)
3370         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3371         return p;
3372 }
3373
3374 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3375 {
3376         char *shaderstring;
3377         if (!filename || !filename[0])
3378                 return NULL;
3379         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3380         if (shaderstring)
3381         {
3382                 if (printfromdisknotice)
3383                         Con_DPrintf("from disk %s... ", filename);
3384                 return shaderstring;
3385         }
3386         else if (!strcmp(filename, "glsl/default.glsl"))
3387         {
3388                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3389                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3390         }
3391         return shaderstring;
3392 }
3393
3394 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3395 {
3396         int i;
3397         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3398         int vertstrings_count = 0;
3399         int geomstrings_count = 0;
3400         int fragstrings_count = 0;
3401         char *vertexstring, *geometrystring, *fragmentstring;
3402         const char *vertstrings_list[32+3];
3403         const char *geomstrings_list[32+3];
3404         const char *fragstrings_list[32+3];
3405         char permutationname[256];
3406
3407         if (p->compiled)
3408                 return;
3409         p->compiled = true;
3410         p->program = 0;
3411
3412         permutationname[0] = 0;
3413         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3414         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3415         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3416
3417         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3418
3419         // the first pretext is which type of shader to compile as
3420         // (later these will all be bound together as a program object)
3421         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3422         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3423         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3424
3425         // the second pretext is the mode (for example a light source)
3426         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3427         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3428         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3429         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3430
3431         // now add all the permutation pretexts
3432         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3433         {
3434                 if (permutation & (1<<i))
3435                 {
3436                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3437                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3438                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3439                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3440                 }
3441                 else
3442                 {
3443                         // keep line numbers correct
3444                         vertstrings_list[vertstrings_count++] = "\n";
3445                         geomstrings_list[geomstrings_count++] = "\n";
3446                         fragstrings_list[fragstrings_count++] = "\n";
3447                 }
3448         }
3449
3450         // now append the shader text itself
3451         vertstrings_list[vertstrings_count++] = vertexstring;
3452         geomstrings_list[geomstrings_count++] = geometrystring;
3453         fragstrings_list[fragstrings_count++] = fragmentstring;
3454
3455         // if any sources were NULL, clear the respective list
3456         if (!vertexstring)
3457                 vertstrings_count = 0;
3458         if (!geometrystring)
3459                 geomstrings_count = 0;
3460         if (!fragmentstring)
3461                 fragstrings_count = 0;
3462
3463         // compile the shader program
3464         if (vertstrings_count + geomstrings_count + fragstrings_count)
3465                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3466         if (p->program)
3467         {
3468                 CHECKGLERROR
3469                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3470                 // look up all the uniform variable names we care about, so we don't
3471                 // have to look them up every time we set them
3472
3473                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3474                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3475                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3476                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3477                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3478                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3479                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3480                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3481                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3482                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3483                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3484                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3485                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3486                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3487                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3488                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3489                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3490                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3491                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3492                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3493                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3494                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3495                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3496                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3497                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3498                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3499                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3500                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3501                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3502                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3503                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3504                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3505                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3506                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3507                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3508                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3509                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3510                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3511                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3512                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3513                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3514                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3515                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3516                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3517                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3518                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3519                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3520                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3521                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3522                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3523                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3524                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3525                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3526                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3527                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3528                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3529                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3530                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3531                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3532                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3533                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3534                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3535                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3536                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3537                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3538                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3539                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3540                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3541                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3542                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3543                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3544                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3545                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3546                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3547                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3548                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3549                 // initialize the samplers to refer to the texture units we use
3550                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3551                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3552                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3553                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3554                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3555                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3556                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3557                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3558                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3559                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3560                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3561                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3562                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3563                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3564                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3565                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3566                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3567                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3568                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3569                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3570                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3571                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3572                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3573                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3574                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3575                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3576                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3577                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3578                 CHECKGLERROR
3579                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3580         }
3581         else
3582                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3583
3584         // free the strings
3585         if (vertexstring)
3586                 Mem_Free(vertexstring);
3587         if (geometrystring)
3588                 Mem_Free(geometrystring);
3589         if (fragmentstring)
3590                 Mem_Free(fragmentstring);
3591 }
3592
3593 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3594 {
3595         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3596         if (r_glsl_permutation != perm)
3597         {
3598                 r_glsl_permutation = perm;
3599                 if (!r_glsl_permutation->program)
3600                 {
3601                         if (!r_glsl_permutation->compiled)
3602                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3603                         if (!r_glsl_permutation->program)
3604                         {
3605                                 // remove features until we find a valid permutation
3606                                 int i;
3607                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3608                                 {
3609                                         // reduce i more quickly whenever it would not remove any bits
3610                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3611                                         if (!(permutation & j))
3612                                                 continue;
3613                                         permutation -= j;
3614                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3615                                         if (!r_glsl_permutation->compiled)
3616                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3617                                         if (r_glsl_permutation->program)
3618                                                 break;
3619                                 }
3620                                 if (i >= SHADERPERMUTATION_COUNT)
3621                                 {
3622                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3623                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3624                                         qglUseProgramObjectARB(0);CHECKGLERROR
3625                                         return; // no bit left to clear, entire mode is broken
3626                                 }
3627                         }
3628                 }
3629                 CHECKGLERROR
3630                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3631         }
3632         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3633         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3634 }
3635
3636 #ifdef SUPPORTCG
3637 #include <Cg/cgGL.h>
3638 struct r_cg_permutation_s;
3639 typedef struct r_cg_permutation_s
3640 {
3641         /// hash lookup data
3642         struct r_cg_permutation_s *hashnext;
3643         unsigned int mode;
3644         unsigned int permutation;
3645
3646         /// indicates if we have tried compiling this permutation already
3647         qboolean compiled;
3648         /// 0 if compilation failed
3649         CGprogram vprogram;
3650         CGprogram fprogram;
3651         /// locations of detected parameters in programs, or NULL if not found
3652         CGparameter vp_EyePosition;
3653         CGparameter vp_FogPlane;
3654         CGparameter vp_LightDir;
3655         CGparameter vp_LightPosition;
3656         CGparameter vp_ModelToLight;
3657         CGparameter vp_TexMatrix;
3658         CGparameter vp_BackgroundTexMatrix;
3659         CGparameter vp_ModelViewProjectionMatrix;
3660         CGparameter vp_ModelViewMatrix;
3661
3662         CGparameter fp_Texture_First;
3663         CGparameter fp_Texture_Second;
3664         CGparameter fp_Texture_GammaRamps;
3665         CGparameter fp_Texture_Normal;
3666         CGparameter fp_Texture_Color;
3667         CGparameter fp_Texture_Gloss;
3668         CGparameter fp_Texture_Glow;
3669         CGparameter fp_Texture_SecondaryNormal;
3670         CGparameter fp_Texture_SecondaryColor;
3671         CGparameter fp_Texture_SecondaryGloss;
3672         CGparameter fp_Texture_SecondaryGlow;
3673         CGparameter fp_Texture_Pants;
3674         CGparameter fp_Texture_Shirt;
3675         CGparameter fp_Texture_FogMask;
3676         CGparameter fp_Texture_Lightmap;
3677         CGparameter fp_Texture_Deluxemap;
3678         CGparameter fp_Texture_Attenuation;
3679         CGparameter fp_Texture_Cube;
3680         CGparameter fp_Texture_Refraction;
3681         CGparameter fp_Texture_Reflection;
3682         CGparameter fp_Texture_ShadowMapRect;
3683         CGparameter fp_Texture_ShadowMapCube;
3684         CGparameter fp_Texture_ShadowMap2D;
3685         CGparameter fp_Texture_CubeProjection;
3686         CGparameter fp_Texture_ScreenDepth;
3687         CGparameter fp_Texture_ScreenNormalMap;
3688         CGparameter fp_Texture_ScreenDiffuse;
3689         CGparameter fp_Texture_ScreenSpecular;
3690         CGparameter fp_Alpha;
3691         CGparameter fp_BloomBlur_Parameters;
3692         CGparameter fp_ClientTime;
3693         CGparameter fp_Color_Ambient;
3694         CGparameter fp_Color_Diffuse;
3695         CGparameter fp_Color_Specular;
3696         CGparameter fp_Color_Glow;
3697         CGparameter fp_Color_Pants;
3698         CGparameter fp_Color_Shirt;
3699         CGparameter fp_DeferredColor_Ambient;
3700         CGparameter fp_DeferredColor_Diffuse;
3701         CGparameter fp_DeferredColor_Specular;
3702         CGparameter fp_DeferredMod_Diffuse;
3703         CGparameter fp_DeferredMod_Specular;
3704         CGparameter fp_DistortScaleRefractReflect;
3705         CGparameter fp_EyePosition;
3706         CGparameter fp_FogColor;
3707         CGparameter fp_FogHeightFade;
3708         CGparameter fp_FogPlane;
3709         CGparameter fp_FogPlaneViewDist;
3710         CGparameter fp_FogRangeRecip;
3711         CGparameter fp_LightColor;
3712         CGparameter fp_LightDir;
3713         CGparameter fp_LightPosition;
3714         CGparameter fp_OffsetMapping_Scale;
3715         CGparameter fp_PixelSize;
3716         CGparameter fp_ReflectColor;
3717         CGparameter fp_ReflectFactor;
3718         CGparameter fp_ReflectOffset;
3719         CGparameter fp_RefractColor;
3720         CGparameter fp_Saturation;
3721         CGparameter fp_ScreenCenterRefractReflect;
3722         CGparameter fp_ScreenScaleRefractReflect;
3723         CGparameter fp_ScreenToDepth;
3724         CGparameter fp_ShadowMap_Parameters;
3725         CGparameter fp_ShadowMap_TextureScale;
3726         CGparameter fp_SpecularPower;
3727         CGparameter fp_UserVec1;
3728         CGparameter fp_UserVec2;
3729         CGparameter fp_UserVec3;
3730         CGparameter fp_UserVec4;
3731         CGparameter fp_ViewTintColor;
3732         CGparameter fp_ViewToLight;
3733 }
3734 r_cg_permutation_t;
3735
3736 /// information about each possible shader permutation
3737 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3738 /// currently selected permutation
3739 r_cg_permutation_t *r_cg_permutation;
3740 /// storage for permutations linked in the hash table
3741 memexpandablearray_t r_cg_permutationarray;
3742
3743 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
3744
3745 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3746 {
3747         //unsigned int hashdepth = 0;
3748         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3749         r_cg_permutation_t *p;
3750         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3751         {
3752                 if (p->mode == mode && p->permutation == permutation)
3753                 {
3754                         //if (hashdepth > 10)
3755                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3756                         return p;
3757                 }
3758                 //hashdepth++;
3759         }
3760         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3761         p->mode = mode;
3762         p->permutation = permutation;
3763         p->hashnext = r_cg_permutationhash[mode][hashindex];
3764         r_cg_permutationhash[mode][hashindex] = p;
3765         //if (hashdepth > 10)
3766         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3767         return p;
3768 }
3769
3770 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3771 {
3772         char *shaderstring;
3773         if (!filename || !filename[0])
3774                 return NULL;
3775         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3776         if (shaderstring)
3777         {
3778                 if (printfromdisknotice)
3779                         Con_DPrintf("from disk %s... ", filename);
3780                 return shaderstring;
3781         }
3782         else if (!strcmp(filename, "cg/default.cg"))
3783         {
3784                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3785                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3786         }
3787         return shaderstring;
3788 }
3789
3790 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3791 {
3792         int i;
3793         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3794         int vertstrings_count = 0, vertstring_length = 0;
3795         int geomstrings_count = 0, geomstring_length = 0;
3796         int fragstrings_count = 0, fragstring_length = 0;
3797         char *t;
3798         char *vertexstring, *geometrystring, *fragmentstring;
3799         char *vertstring, *geomstring, *fragstring;
3800         const char *vertstrings_list[32+3];
3801         const char *geomstrings_list[32+3];
3802         const char *fragstrings_list[32+3];
3803         char permutationname[256];
3804         CGprofile vertexProfile;
3805         CGprofile fragmentProfile;
3806
3807         if (p->compiled)
3808                 return;
3809         p->compiled = true;
3810         p->vprogram = NULL;
3811         p->fprogram = NULL;
3812
3813         permutationname[0] = 0;
3814         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3815         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3816         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3817
3818         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3819
3820         // the first pretext is which type of shader to compile as
3821         // (later these will all be bound together as a program object)
3822         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3823         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3824         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3825
3826         // the second pretext is the mode (for example a light source)
3827         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3828         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3829         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3830         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3831
3832         // now add all the permutation pretexts
3833         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3834         {
3835                 if (permutation & (1<<i))
3836                 {
3837                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3838                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3839                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3840                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3841                 }
3842                 else
3843                 {
3844                         // keep line numbers correct
3845                         vertstrings_list[vertstrings_count++] = "\n";
3846                         geomstrings_list[geomstrings_count++] = "\n";
3847                         fragstrings_list[fragstrings_count++] = "\n";
3848                 }
3849         }
3850
3851         // now append the shader text itself
3852         vertstrings_list[vertstrings_count++] = vertexstring;
3853         geomstrings_list[geomstrings_count++] = geometrystring;
3854         fragstrings_list[fragstrings_count++] = fragmentstring;
3855
3856         // if any sources were NULL, clear the respective list
3857         if (!vertexstring)
3858                 vertstrings_count = 0;
3859         if (!geometrystring)
3860                 geomstrings_count = 0;
3861         if (!fragmentstring)
3862                 fragstrings_count = 0;
3863
3864         vertstring_length = 0;
3865         for (i = 0;i < vertstrings_count;i++)
3866                 vertstring_length += strlen(vertstrings_list[i]);
3867         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3868         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3869                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3870
3871         geomstring_length = 0;
3872         for (i = 0;i < geomstrings_count;i++)
3873                 geomstring_length += strlen(geomstrings_list[i]);
3874         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3875         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3876                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3877
3878         fragstring_length = 0;
3879         for (i = 0;i < fragstrings_count;i++)
3880                 fragstring_length += strlen(fragstrings_list[i]);
3881         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3882         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3883                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3884
3885         CHECKGLERROR
3886         CHECKCGERROR
3887         //vertexProfile = CG_PROFILE_ARBVP1;
3888         //fragmentProfile = CG_PROFILE_ARBFP1;
3889         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3890         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3891         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3892         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3893         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3894         CHECKGLERROR
3895
3896         // compile the vertex program
3897         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL)))
3898         {
3899                 CHECKCGERROR
3900                 cgCompileProgram(p->vprogram);CHECKCGERROR
3901                 if (!cgIsProgramCompiled(p->vprogram))
3902                 {
3903                         CHECKCGERROR
3904                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3905                         p->vprogram = 0;
3906                 }
3907                 else
3908                 {
3909                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3910                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3911                         // look up all the uniform variable names we care about, so we don't
3912                         // have to look them up every time we set them
3913                         CHECKCGERROR
3914                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3915                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3916                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3917                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3918                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3919                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3920                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3921                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3922                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3923                         CHECKCGERROR
3924                 }
3925         }
3926
3927         // compile the fragment program
3928         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL)))
3929         {
3930                 cgCompileProgram(p->fprogram);CHECKCGERROR
3931                 if (!cgIsProgramCompiled(p->fprogram))
3932                 {
3933                         CHECKCGERROR
3934                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3935                         p->fprogram = 0;
3936                 }
3937                 else
3938                 {
3939                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3940                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3941                         CHECKCGERROR
3942                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3943                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3944                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3945                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3946                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3947                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3948                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3949                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3950                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3951                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3952                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3953                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3954                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3955                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3956                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3957                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3958                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3959                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3960                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3961                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3962                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3963                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3964                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3965                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3966                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3967                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3968                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3969                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3970                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
3971                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3972                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
3973                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
3974                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
3975                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
3976                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
3977                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
3978                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
3979                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
3980                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
3981                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
3982                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
3983                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
3984                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
3985                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
3986                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
3987                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
3988                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
3989                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
3990                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
3991                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
3992                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
3993                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
3994                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
3995                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
3996                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
3997                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
3998                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
3999                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4000                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4001                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4002                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4003                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4004                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4005                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4006                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4007                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4008                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4009                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4010                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4011                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4012                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4013                         CHECKCGERROR
4014                 }
4015         }
4016
4017         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4018                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4019         else
4020                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4021
4022         // free the strings
4023         if (vertstring)
4024                 Mem_Free(vertstring);
4025         if (geomstring)
4026                 Mem_Free(geomstring);
4027         if (fragstring)
4028                 Mem_Free(fragstring);
4029         if (vertexstring)
4030                 Mem_Free(vertexstring);
4031         if (geometrystring)
4032                 Mem_Free(geometrystring);
4033         if (fragmentstring)
4034                 Mem_Free(fragmentstring);
4035 }
4036
4037 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4038 {
4039         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4040         CHECKGLERROR
4041         CHECKCGERROR
4042         if (r_cg_permutation != perm)
4043         {
4044                 r_cg_permutation = perm;
4045                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4046                 {
4047                         if (!r_cg_permutation->compiled)
4048                                 R_CG_CompilePermutation(perm, mode, permutation);
4049                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4050                         {
4051                                 // remove features until we find a valid permutation
4052                                 int i;
4053                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4054                                 {
4055                                         // reduce i more quickly whenever it would not remove any bits
4056                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4057                                         if (!(permutation & j))
4058                                                 continue;
4059                                         permutation -= j;
4060                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4061                                         if (!r_cg_permutation->compiled)
4062                                                 R_CG_CompilePermutation(perm, mode, permutation);
4063                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4064                                                 break;
4065                                 }
4066                                 if (i >= SHADERPERMUTATION_COUNT)
4067                                 {
4068                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4069                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4070                                         return; // no bit left to clear, entire mode is broken
4071                                 }
4072                         }
4073                 }
4074                 CHECKGLERROR
4075                 CHECKCGERROR
4076                 if (r_cg_permutation->vprogram)
4077                 {
4078                         //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4079                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4080                         //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4081                 }
4082                 else
4083                 {
4084                         //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4085                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4086                 }
4087                 if (r_cg_permutation->fprogram)
4088                 {
4089                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4090                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4091                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4092                 }
4093                 else
4094                 {
4095                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4096                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4097                 }
4098         }
4099         CHECKCGERROR
4100         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4101         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4102 }
4103
4104 void CG_BindTexture(CGparameter param, int texnum)
4105 {
4106         cgGLSetTextureParameter(param, texnum);
4107         cgGLEnableTextureParameter(param);
4108 }
4109 #endif
4110
4111 void R_GLSL_Restart_f(void)
4112 {
4113         unsigned int i, limit;
4114         switch(vid.renderpath)
4115         {
4116         case RENDERPATH_GL20:
4117                 {
4118                         r_glsl_permutation_t *p;
4119                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4120                         for (i = 0;i < limit;i++)
4121                         {
4122                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4123                                 {
4124                                         GL_Backend_FreeProgram(p->program);
4125                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4126                                 }
4127                         }
4128                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4129                 }
4130                 break;
4131         case RENDERPATH_CGGL:
4132 #ifdef SUPPORTCG
4133                 {
4134                         r_cg_permutation_t *p;
4135                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4136                         for (i = 0;i < limit;i++)
4137                         {
4138                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4139                                 {
4140                                         if (p->vprogram)
4141                                                 cgDestroyProgram(p->vprogram);
4142                                         if (p->fprogram)
4143                                                 cgDestroyProgram(p->fprogram);
4144                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4145                                 }
4146                         }
4147                 }
4148                 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4149                 break;
4150 #endif
4151         case RENDERPATH_GL13:
4152         case RENDERPATH_GL11:
4153                 break;
4154         }
4155 }
4156
4157 void R_GLSL_DumpShader_f(void)
4158 {
4159         int i;
4160         qfile_t *file;
4161
4162         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4163         if (file)
4164         {
4165                 FS_Print(file, "/* The engine may define the following macros:\n");
4166                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4167                 for (i = 0;i < SHADERMODE_COUNT;i++) {
4168                         if (glslshadermodeinfo[i].pretext)
4169                                 FS_Print(file, glslshadermodeinfo[i].pretext);
4170                 }
4171                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++) {
4172                         if (shaderpermutationinfo[i].pretext)
4173                                 FS_Print(file, shaderpermutationinfo[i].pretext);
4174                 }
4175                 FS_Print(file, "*/\n");
4176                 FS_Print(file, builtinshaderstring);
4177                 FS_Close(file);
4178                 Con_Printf("glsl/default.glsl written\n");
4179         }
4180         else
4181                 Con_Printf("failed to write to glsl/default.glsl\n");
4182
4183 #ifdef SUPPORTCG
4184         file = FS_OpenRealFile("cg/default.cg", "w", false);
4185         if (file)
4186         {
4187                 FS_Print(file, "/* The engine may define the following macros:\n");
4188                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4189                 for (i = 0;i < SHADERMODE_COUNT;i++)
4190                         FS_Print(file, cgshadermodeinfo[i].pretext);
4191                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4192                         FS_Print(file, shaderpermutationinfo[i].pretext);
4193                 FS_Print(file, "*/\n");
4194                 FS_Print(file, builtincgshaderstring);
4195                 FS_Close(file);
4196                 Con_Printf("cg/default.cg written\n");
4197         }
4198         else
4199                 Con_Printf("failed to write to cg/default.cg\n");
4200 #endif
4201 }
4202
4203 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4204 {
4205         if (!second)
4206                 texturemode = GL_MODULATE;
4207         switch (vid.renderpath)
4208         {
4209         case RENDERPATH_GL20:
4210                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4211                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4212                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4213                 break;
4214         case RENDERPATH_CGGL:
4215 #ifdef SUPPORTCG
4216                 CHECKCGERROR
4217                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4218                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4219                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4220 #endif
4221                 break;
4222         case RENDERPATH_GL13:
4223                 R_Mesh_TexBind(0, first );
4224                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4225                 R_Mesh_TexBind(1, second);
4226                 if (second)
4227                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4228                 break;
4229         case RENDERPATH_GL11:
4230                 R_Mesh_TexBind(0, first );
4231                 break;
4232         }
4233 }
4234
4235 void R_SetupShader_DepthOrShadow(void)
4236 {
4237         switch (vid.renderpath)
4238         {
4239         case RENDERPATH_GL20:
4240                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4241                 break;
4242         case RENDERPATH_CGGL:
4243 #ifdef SUPPORTCG
4244                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4245 #endif
4246                 break;
4247         case RENDERPATH_GL13:
4248                 R_Mesh_TexBind(0, 0);
4249                 R_Mesh_TexBind(1, 0);
4250                 break;
4251         case RENDERPATH_GL11:
4252                 R_Mesh_TexBind(0, 0);
4253                 break;
4254         }
4255 }
4256
4257 void R_SetupShader_ShowDepth(void)
4258 {
4259         switch (vid.renderpath)
4260         {
4261         case RENDERPATH_GL20:
4262                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4263                 break;
4264         case RENDERPATH_CGGL:
4265 #ifdef SUPPORTCG
4266                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4267 #endif
4268                 break;
4269         case RENDERPATH_GL13:
4270                 break;
4271         case RENDERPATH_GL11:
4272                 break;
4273         }
4274 }
4275
4276 extern qboolean r_shadow_usingdeferredprepass;
4277 extern cvar_t r_shadow_deferred_8bitrange;
4278 extern rtexture_t *r_shadow_attenuationgradienttexture;
4279 extern rtexture_t *r_shadow_attenuation2dtexture;
4280 extern rtexture_t *r_shadow_attenuation3dtexture;
4281 extern qboolean r_shadow_usingshadowmaprect;
4282 extern qboolean r_shadow_usingshadowmapcube;
4283 extern qboolean r_shadow_usingshadowmap2d;
4284 extern float r_shadow_shadowmap_texturescale[2];
4285 extern float r_shadow_shadowmap_parameters[4];
4286 extern qboolean r_shadow_shadowmapvsdct;
4287 extern qboolean r_shadow_shadowmapsampler;
4288 extern int r_shadow_shadowmappcf;
4289 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4290 extern rtexture_t *r_shadow_shadowmap2dtexture;
4291 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4292 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4293 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4294 extern int r_shadow_prepass_width;
4295 extern int r_shadow_prepass_height;
4296 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4297 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4298 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4299 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4300 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4301 {
4302         // select a permutation of the lighting shader appropriate to this
4303         // combination of texture, entity, light source, and fogging, only use the
4304         // minimum features necessary to avoid wasting rendering time in the
4305         // fragment shader on features that are not being used
4306         unsigned int permutation = 0;
4307         unsigned int mode = 0;
4308         float m16f[16];
4309         // TODO: implement geometry-shader based shadow volumes someday
4310         if (r_glsl_offsetmapping.integer)
4311         {
4312                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4313                 if (r_glsl_offsetmapping_reliefmapping.integer)
4314                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4315         }
4316         if (rsurfacepass == RSURFPASS_BACKGROUND)
4317         {
4318                 // distorted background
4319                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4320                         mode = SHADERMODE_WATER;
4321                 else
4322                         mode = SHADERMODE_REFRACTION;
4323         }
4324         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4325         {
4326                 // normalmap (deferred prepass), may use alpha test on diffuse
4327                 mode = SHADERMODE_DEFERREDGEOMETRY;
4328                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4329                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4330                 if (r_glsl_offsetmapping.integer)
4331                 {
4332                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4333                         if (r_glsl_offsetmapping_reliefmapping.integer)
4334                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4335                 }
4336         }
4337         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4338         {
4339                 // light source
4340                 mode = SHADERMODE_LIGHTSOURCE;
4341                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4342                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4343                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4344                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4345                 if (diffusescale > 0)
4346                         permutation |= SHADERPERMUTATION_DIFFUSE;
4347                 if (specularscale > 0)
4348                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4349                 if (r_refdef.fogenabled)
4350                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4351                 if (rsurface.texture->colormapping)
4352                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4353                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4354                 {
4355                         if (r_shadow_usingshadowmaprect)
4356                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4357                         if (r_shadow_usingshadowmap2d)
4358                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4359                         if (r_shadow_usingshadowmapcube)
4360                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4361                         else if(r_shadow_shadowmapvsdct)
4362                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4363
4364                         if (r_shadow_shadowmapsampler)
4365                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4366                         if (r_shadow_shadowmappcf > 1)
4367                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4368                         else if (r_shadow_shadowmappcf)
4369                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4370                 }
4371         }
4372         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4373         {
4374                 // unshaded geometry (fullbright or ambient model lighting)
4375                 mode = SHADERMODE_FLATCOLOR;
4376                 ambientscale = diffusescale = specularscale = 0;
4377                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4378                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4379                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4380                         permutation |= SHADERPERMUTATION_GLOW;
4381                 if (r_refdef.fogenabled)
4382                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4383                 if (rsurface.texture->colormapping)
4384                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4385                 if (r_glsl_offsetmapping.integer)
4386                 {
4387                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4388                         if (r_glsl_offsetmapping_reliefmapping.integer)
4389                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4390                 }
4391                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4392                         permutation |= SHADERPERMUTATION_REFLECTION;
4393         }
4394         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4395         {
4396                 // directional model lighting
4397                 mode = SHADERMODE_LIGHTDIRECTION;
4398                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4399                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4400                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4401                         permutation |= SHADERPERMUTATION_GLOW;
4402                 permutation |= SHADERPERMUTATION_DIFFUSE;
4403                 if (specularscale > 0)
4404                         permutation |= SHADERPERMUTATION_SPECULAR;
4405                 if (r_refdef.fogenabled)
4406                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4407                 if (rsurface.texture->colormapping)
4408                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4409                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4410                         permutation |= SHADERPERMUTATION_REFLECTION;
4411                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4412                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4413         }
4414         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4415         {
4416                 // ambient model lighting
4417                 mode = SHADERMODE_LIGHTDIRECTION;
4418                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4419                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4420                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4421                         permutation |= SHADERPERMUTATION_GLOW;
4422                 if (r_refdef.fogenabled)
4423                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4424                 if (rsurface.texture->colormapping)
4425                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4426                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4427                         permutation |= SHADERPERMUTATION_REFLECTION;
4428                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4429                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4430         }
4431         else
4432         {
4433                 // lightmapped wall
4434                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4435                 {
4436                         // deluxemapping (light direction texture)
4437                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4438                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4439                         else
4440                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4441                         permutation |= SHADERPERMUTATION_DIFFUSE;
4442                         if (specularscale > 0)
4443                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4444                 }
4445                 else if (r_glsl_deluxemapping.integer >= 2)
4446                 {
4447                         // fake deluxemapping (uniform light direction in tangentspace)
4448                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4449                         permutation |= SHADERPERMUTATION_DIFFUSE;
4450                         if (specularscale > 0)
4451                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4452                 }
4453                 else if (rsurface.uselightmaptexture)
4454                 {
4455                         // ordinary lightmapping (q1bsp, q3bsp)
4456                         mode = SHADERMODE_LIGHTMAP;
4457                 }
4458                 else
4459                 {
4460                         // ordinary vertex coloring (q3bsp)
4461                         mode = SHADERMODE_VERTEXCOLOR;
4462                 }
4463                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4464                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
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                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4474                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4475         }
4476         if(permutation & SHADERPERMUTATION_SPECULAR)
4477                 if(r_shadow_glossexact.integer)
4478                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4479         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
4480                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4481         switch(vid.renderpath)
4482         {
4483         case RENDERPATH_GL20:
4484                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4485                 if (mode == SHADERMODE_LIGHTSOURCE)
4486                 {
4487                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4488                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4489                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4490                         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);
4491                         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);
4492                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
4493         
4494                         // additive passes are only darkened by fog, not tinted
4495                         if (r_glsl_permutation->loc_FogColor >= 0)
4496                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4497                         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]);
4498                         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]);
4499                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4500                 }
4501                 else
4502                 {
4503                         if (mode == SHADERMODE_FLATCOLOR)
4504                         {
4505                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4506                         }
4507                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4508                         {
4509                                 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]);
4510                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
4511                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
4512                                 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);
4513                                 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);
4514                                 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]);
4515                                 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]);
4516                         }
4517                         else
4518                         {
4519                                 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]);
4520                                 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]);
4521                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
4522                                 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);
4523                                 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);
4524                         }
4525                         // additive passes are only darkened by fog, not tinted
4526                         if (r_glsl_permutation->loc_FogColor >= 0)
4527                         {
4528                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4529                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4530                                 else
4531                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4532                         }
4533                         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);
4534                         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]);
4535                         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]);
4536                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4537                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4538                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4539                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4540                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4541                 }
4542                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4543                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4544                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4545                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4546                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4547                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4548                 {
4549                         if (rsurface.texture->pantstexture)
4550                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4551                         else
4552                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4553                 }
4554                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4555                 {
4556                         if (rsurface.texture->shirttexture)
4557                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4558                         else
4559                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4560                 }
4561                 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]);
4562                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4563                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4564                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4565                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4566                 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]);
4567
4568         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4569         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4570         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4571                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4572                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4573                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4574                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4575                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4576                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4577                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4578                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4579                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4580                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4581                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4582                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4583                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4584                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4585                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4586                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4587                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4588                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4589                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4590                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4591                 if (rsurface.rtlight)
4592                 {
4593                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4594                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4595                         if (r_shadow_usingshadowmapcube)
4596                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4597                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4598                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4599                 }
4600                 CHECKGLERROR
4601                 break;
4602         case RENDERPATH_CGGL:
4603 #ifdef SUPPORTCG
4604                 R_SetupShader_SetPermutationCG(mode, permutation);
4605                 if (mode == SHADERMODE_LIGHTSOURCE)
4606                 {
4607                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4608                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4609                 }
4610                 else
4611                 {
4612                         if (mode == SHADERMODE_LIGHTDIRECTION)
4613                         {
4614                                 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
4615                         }
4616                 }
4617                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4618                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4619                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4620                 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
4621                 CHECKGLERROR
4622
4623                 if (mode == SHADERMODE_LIGHTSOURCE)
4624                 {
4625                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4626                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4627                         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
4628                         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
4629                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);CHECKCGERROR
4630
4631                         // additive passes are only darkened by fog, not tinted
4632                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4633                         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
4634                         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
4635                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4636                 }
4637                 else
4638                 {
4639                         if (mode == SHADERMODE_FLATCOLOR)
4640                         {
4641                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4642                         }
4643                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4644                         {
4645                                 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
4646                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);CHECKCGERROR
4647                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);CHECKCGERROR
4648                                 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
4649                                 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
4650                                 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
4651                                 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
4652                         }
4653                         else
4654                         {
4655                                 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
4656                                 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
4657                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);CHECKCGERROR
4658                                 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
4659                                 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
4660                         }
4661                         // additive passes are only darkened by fog, not tinted
4662                         if (r_cg_permutation->fp_FogColor)
4663                         {
4664                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4665                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4666                                 else
4667                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4668                                 CHECKCGERROR
4669                         }
4670                         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
4671                         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
4672                         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
4673                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4674                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4675                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4676                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4677                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4678                 }
4679                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4680                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4681                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4682                 if (r_cg_permutation->fp_Color_Pants)
4683                 {
4684                         if (rsurface.texture->pantstexture)
4685                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4686                         else
4687                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4688                         CHECKCGERROR
4689                 }
4690                 if (r_cg_permutation->fp_Color_Shirt)
4691                 {
4692                         if (rsurface.texture->shirttexture)
4693                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4694                         else
4695                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4696                         CHECKCGERROR
4697                 }
4698                 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
4699                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4700                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4701                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4702                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4703                 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
4704
4705         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
4706         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
4707         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
4708                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
4709                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
4710                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
4711                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
4712                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
4713                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
4714                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
4715                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
4716                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
4717                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
4718                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
4719                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
4720                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
4721                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4722                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
4723                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
4724                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4725                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4726                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
4727                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
4728                 if (rsurface.rtlight)
4729                 {
4730                         if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4731                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4732                         if (r_shadow_usingshadowmapcube)
4733                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4734                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4735                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4736                 }
4737
4738                 CHECKGLERROR
4739 #endif
4740                 break;
4741         case RENDERPATH_GL13:
4742         case RENDERPATH_GL11:
4743                 break;
4744         }
4745 }
4746
4747 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4748 {
4749         // select a permutation of the lighting shader appropriate to this
4750         // combination of texture, entity, light source, and fogging, only use the
4751         // minimum features necessary to avoid wasting rendering time in the
4752         // fragment shader on features that are not being used
4753         unsigned int permutation = 0;
4754         unsigned int mode = 0;
4755         const float *lightcolorbase = rtlight->currentcolor;
4756         float ambientscale = rtlight->ambientscale;
4757         float diffusescale = rtlight->diffusescale;
4758         float specularscale = rtlight->specularscale;
4759         // this is the location of the light in view space
4760         vec3_t viewlightorigin;
4761         // this transforms from view space (camera) to light space (cubemap)
4762         matrix4x4_t viewtolight;
4763         matrix4x4_t lighttoview;
4764         float viewtolight16f[16];
4765         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4766         // light source
4767         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4768         if (rtlight->currentcubemap != r_texture_whitecube)
4769                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4770         if (diffusescale > 0)
4771                 permutation |= SHADERPERMUTATION_DIFFUSE;
4772         if (specularscale > 0)
4773         {
4774                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4775                 if (r_shadow_glossexact.integer)
4776                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4777         }
4778         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4779         {
4780                 if (r_shadow_usingshadowmaprect)
4781                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4782                 if (r_shadow_usingshadowmap2d)
4783                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4784                 if (r_shadow_usingshadowmapcube)
4785                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4786                 else if(r_shadow_shadowmapvsdct)
4787                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4788
4789                 if (r_shadow_shadowmapsampler)
4790                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4791                 if (r_shadow_shadowmappcf > 1)
4792                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4793                 else if (r_shadow_shadowmappcf)
4794                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4795         }
4796         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4797         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4798         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4799         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4800         switch(vid.renderpath)
4801         {
4802         case RENDERPATH_GL20:
4803                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4804                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4805                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4806                 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);
4807                 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);
4808                 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);
4809                 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]);
4810                 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]);
4811                 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));
4812                 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]);
4813
4814                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
4815                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
4816                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
4817                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
4818                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
4819                 if (r_shadow_usingshadowmapcube)
4820                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4821                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
4822                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
4823                 break;
4824         case RENDERPATH_CGGL:
4825 #ifdef SUPPORTCG
4826                 R_SetupShader_SetPermutationCG(mode, permutation);
4827                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4828                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4829                 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
4830                 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
4831                 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
4832                 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
4833                 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
4834                 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
4835                 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
4836
4837                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4838                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4839                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4840                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4841                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4842                 if (r_shadow_usingshadowmapcube)
4843                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4844                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4845                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4846 #endif
4847                 break;
4848         case RENDERPATH_GL13:
4849         case RENDERPATH_GL11:
4850                 break;
4851         }
4852 }
4853
4854 #define SKINFRAME_HASH 1024
4855
4856 typedef struct
4857 {
4858         int loadsequence; // incremented each level change
4859         memexpandablearray_t array;
4860         skinframe_t *hash[SKINFRAME_HASH];
4861 }
4862 r_skinframe_t;
4863 r_skinframe_t r_skinframe;
4864
4865 void R_SkinFrame_PrepareForPurge(void)
4866 {
4867         r_skinframe.loadsequence++;
4868         // wrap it without hitting zero
4869         if (r_skinframe.loadsequence >= 200)
4870                 r_skinframe.loadsequence = 1;
4871 }
4872
4873 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
4874 {
4875         if (!skinframe)
4876                 return;
4877         // mark the skinframe as used for the purging code
4878         skinframe->loadsequence = r_skinframe.loadsequence;
4879 }
4880
4881 void R_SkinFrame_Purge(void)
4882 {
4883         int i;
4884         skinframe_t *s;
4885         for (i = 0;i < SKINFRAME_HASH;i++)
4886         {
4887                 for (s = r_skinframe.hash[i];s;s = s->next)
4888                 {
4889                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
4890                         {
4891                                 if (s->merged == s->base)
4892                                         s->merged = NULL;
4893                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
4894                                 R_PurgeTexture(s->stain );s->stain  = NULL;
4895                                 R_PurgeTexture(s->merged);s->merged = NULL;
4896                                 R_PurgeTexture(s->base  );s->base   = NULL;
4897                                 R_PurgeTexture(s->pants );s->pants  = NULL;
4898                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
4899                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
4900                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
4901                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
4902                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
4903                                 s->loadsequence = 0;
4904                         }
4905                 }
4906         }
4907 }
4908
4909 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
4910         skinframe_t *item;
4911         char basename[MAX_QPATH];
4912
4913         Image_StripImageExtension(name, basename, sizeof(basename));
4914
4915         if( last == NULL ) {
4916                 int hashindex;
4917                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4918                 item = r_skinframe.hash[hashindex];
4919         } else {
4920                 item = last->next;
4921         }
4922
4923         // linearly search through the hash bucket
4924         for( ; item ; item = item->next ) {
4925                 if( !strcmp( item->basename, basename ) ) {
4926                         return item;
4927                 }
4928         }
4929         return NULL;
4930 }
4931
4932 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
4933 {
4934         skinframe_t *item;
4935         int hashindex;
4936         char basename[MAX_QPATH];
4937
4938         Image_StripImageExtension(name, basename, sizeof(basename));
4939
4940         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4941         for (item = r_skinframe.hash[hashindex];item;item = item->next)
4942                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
4943                         break;
4944
4945         if (!item) {
4946                 rtexture_t *dyntexture;
4947                 // check whether its a dynamic texture
4948                 dyntexture = CL_GetDynTexture( basename );
4949                 if (!add && !dyntexture)
4950                         return NULL;
4951                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
4952                 memset(item, 0, sizeof(*item));
4953                 strlcpy(item->basename, basename, sizeof(item->basename));
4954                 item->base = dyntexture; // either NULL or dyntexture handle
4955                 item->textureflags = textureflags;
4956                 item->comparewidth = comparewidth;
4957                 item->compareheight = compareheight;
4958                 item->comparecrc = comparecrc;
4959                 item->next = r_skinframe.hash[hashindex];
4960                 r_skinframe.hash[hashindex] = item;
4961         }
4962         else if( item->base == NULL )
4963         {
4964                 rtexture_t *dyntexture;
4965                 // check whether its a dynamic texture
4966                 // 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]
4967                 dyntexture = CL_GetDynTexture( basename );
4968                 item->base = dyntexture; // either NULL or dyntexture handle
4969         }
4970
4971         R_SkinFrame_MarkUsed(item);
4972         return item;
4973 }
4974
4975 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
4976         { \
4977                 unsigned long long avgcolor[5], wsum; \
4978                 int pix, comp, w; \
4979                 avgcolor[0] = 0; \
4980                 avgcolor[1] = 0; \
4981                 avgcolor[2] = 0; \
4982                 avgcolor[3] = 0; \
4983                 avgcolor[4] = 0; \
4984                 wsum = 0; \
4985                 for(pix = 0; pix < cnt; ++pix) \
4986                 { \
4987                         w = 0; \
4988                         for(comp = 0; comp < 3; ++comp) \
4989                                 w += getpixel; \
4990                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
4991                         { \
4992                                 ++wsum; \
4993                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4994                                 w = getpixel; \
4995                                 for(comp = 0; comp < 3; ++comp) \
4996                                         avgcolor[comp] += getpixel * w; \
4997                                 avgcolor[3] += w; \
4998                         } \
4999                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5000                         avgcolor[4] += getpixel; \
5001                 } \
5002                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5003                         avgcolor[3] = 1; \
5004                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5005                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5006                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5007                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5008         }
5009
5010 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5011 {
5012         int j;
5013         unsigned char *pixels;
5014         unsigned char *bumppixels;
5015         unsigned char *basepixels = NULL;
5016         int basepixels_width = 0;
5017         int basepixels_height = 0;
5018         skinframe_t *skinframe;
5019         rtexture_t *ddsbase = NULL;
5020         qboolean ddshasalpha = false;
5021         float ddsavgcolor[4];
5022         char basename[MAX_QPATH];
5023
5024         if (cls.state == ca_dedicated)
5025                 return NULL;
5026
5027         // return an existing skinframe if already loaded
5028         // if loading of the first image fails, don't make a new skinframe as it
5029         // would cause all future lookups of this to be missing
5030         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5031         if (skinframe && skinframe->base)
5032                 return skinframe;
5033
5034         Image_StripImageExtension(name, basename, sizeof(basename));
5035
5036         // check for DDS texture file first
5037         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5038         {
5039                 basepixels = loadimagepixelsbgra(name, complain, true);
5040                 if (basepixels == NULL)
5041                         return NULL;
5042         }
5043
5044         if (developer_loading.integer)
5045                 Con_Printf("loading skin \"%s\"\n", name);
5046
5047         // we've got some pixels to store, so really allocate this new texture now
5048         if (!skinframe)
5049                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5050         skinframe->stain = NULL;
5051         skinframe->merged = NULL;
5052         skinframe->base = NULL;
5053         skinframe->pants = NULL;
5054         skinframe->shirt = NULL;
5055         skinframe->nmap = NULL;
5056         skinframe->gloss = NULL;
5057         skinframe->glow = NULL;
5058         skinframe->fog = NULL;
5059         skinframe->hasalpha = false;
5060
5061         if (ddsbase)
5062         {
5063                 skinframe->base = ddsbase;
5064                 skinframe->hasalpha = ddshasalpha;
5065                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5066                 if (r_loadfog && skinframe->hasalpha)
5067                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5068                 //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]);
5069         }
5070         else
5071         {
5072                 basepixels_width = image_width;
5073                 basepixels_height = image_height;
5074                 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);
5075                 if (textureflags & TEXF_ALPHA)
5076                 {
5077                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5078                         {
5079                                 if (basepixels[j] < 255)
5080                                 {
5081                                         skinframe->hasalpha = true;
5082                                         break;
5083                                 }
5084                         }
5085                         if (r_loadfog && skinframe->hasalpha)
5086                         {
5087                                 // has transparent pixels
5088                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5089                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5090                                 {
5091                                         pixels[j+0] = 255;
5092                                         pixels[j+1] = 255;
5093                                         pixels[j+2] = 255;
5094                                         pixels[j+3] = basepixels[j+3];
5095                                 }
5096                                 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);
5097                                 Mem_Free(pixels);
5098                         }
5099                 }
5100                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5101                 //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]);
5102                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5103                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5104                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5105                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5106         }
5107
5108         if (r_loaddds)
5109         {
5110                 if (r_loadnormalmap)
5111                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5112                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5113                 if (r_loadgloss)
5114                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5115                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5116                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5117         }
5118
5119         // _norm is the name used by tenebrae and has been adopted as standard
5120         if (r_loadnormalmap && skinframe->nmap == NULL)
5121         {
5122                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5123                 {
5124                         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);
5125                         Mem_Free(pixels);
5126                         pixels = NULL;
5127                 }
5128                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5129                 {
5130                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5131                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5132                         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);
5133                         Mem_Free(pixels);
5134                         Mem_Free(bumppixels);
5135                 }
5136                 else if (r_shadow_bumpscale_basetexture.value > 0)
5137                 {
5138                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5139                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5140                         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);
5141                         Mem_Free(pixels);
5142                 }
5143                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5144                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5145         }
5146
5147         // _luma is supported only for tenebrae compatibility
5148         // _glow is the preferred name
5149         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5150         {
5151                 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);
5152                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5153                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5154                 Mem_Free(pixels);pixels = NULL;
5155         }
5156
5157         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5158         {
5159                 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);
5160                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5161                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5162                 Mem_Free(pixels);
5163                 pixels = NULL;
5164         }
5165
5166         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5167         {
5168                 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);
5169                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5170                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5171                 Mem_Free(pixels);
5172                 pixels = NULL;
5173         }
5174
5175         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5176         {
5177                 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);
5178                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5179                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5180                 Mem_Free(pixels);
5181                 pixels = NULL;
5182         }
5183
5184         if (basepixels)
5185                 Mem_Free(basepixels);
5186
5187         return skinframe;
5188 }
5189
5190 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5191 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5192 {
5193         int i;
5194         unsigned char *temp1, *temp2;
5195         skinframe_t *skinframe;
5196
5197         if (cls.state == ca_dedicated)
5198                 return NULL;
5199
5200         // if already loaded just return it, otherwise make a new skinframe
5201         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5202         if (skinframe && skinframe->base)
5203                 return skinframe;
5204
5205         skinframe->stain = NULL;
5206         skinframe->merged = NULL;
5207         skinframe->base = NULL;
5208         skinframe->pants = NULL;
5209         skinframe->shirt = NULL;
5210         skinframe->nmap = NULL;
5211         skinframe->gloss = NULL;
5212         skinframe->glow = NULL;
5213         skinframe->fog = NULL;
5214         skinframe->hasalpha = false;
5215
5216         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5217         if (!skindata)
5218                 return NULL;
5219
5220         if (developer_loading.integer)
5221                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5222
5223         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5224         {
5225                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5226                 temp2 = temp1 + width * height * 4;
5227                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5228                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5229                 Mem_Free(temp1);
5230         }
5231         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5232         if (textureflags & TEXF_ALPHA)
5233         {
5234                 for (i = 3;i < width * height * 4;i += 4)
5235                 {
5236                         if (skindata[i] < 255)
5237                         {
5238                                 skinframe->hasalpha = true;
5239                                 break;
5240                         }
5241                 }
5242                 if (r_loadfog && skinframe->hasalpha)
5243                 {
5244                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5245                         memcpy(fogpixels, skindata, width * height * 4);
5246                         for (i = 0;i < width * height * 4;i += 4)
5247                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5248                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5249                         Mem_Free(fogpixels);
5250                 }
5251         }
5252
5253         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5254         //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]);
5255
5256         return skinframe;
5257 }
5258
5259 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5260 {
5261         int i;
5262         int featuresmask;
5263         skinframe_t *skinframe;
5264
5265         if (cls.state == ca_dedicated)
5266                 return NULL;
5267
5268         // if already loaded just return it, otherwise make a new skinframe
5269         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5270         if (skinframe && skinframe->base)
5271                 return skinframe;
5272
5273         skinframe->stain = NULL;
5274         skinframe->merged = NULL;
5275         skinframe->base = NULL;
5276         skinframe->pants = NULL;
5277         skinframe->shirt = NULL;
5278         skinframe->nmap = NULL;
5279         skinframe->gloss = NULL;
5280         skinframe->glow = NULL;
5281         skinframe->fog = NULL;
5282         skinframe->hasalpha = false;
5283
5284         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5285         if (!skindata)
5286                 return NULL;
5287
5288         if (developer_loading.integer)
5289                 Con_Printf("loading quake skin \"%s\"\n", name);
5290
5291         // 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)
5292         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5293         memcpy(skinframe->qpixels, skindata, width*height);
5294         skinframe->qwidth = width;
5295         skinframe->qheight = height;
5296
5297         featuresmask = 0;
5298         for (i = 0;i < width * height;i++)
5299                 featuresmask |= palette_featureflags[skindata[i]];
5300
5301         skinframe->hasalpha = false;
5302         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5303         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5304         skinframe->qgeneratemerged = true;
5305         skinframe->qgeneratebase = skinframe->qhascolormapping;
5306         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5307
5308         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5309         //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]);
5310
5311         return skinframe;
5312 }
5313
5314 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5315 {
5316         int width;
5317         int height;
5318         unsigned char *skindata;
5319
5320         if (!skinframe->qpixels)
5321                 return;
5322
5323         if (!skinframe->qhascolormapping)
5324                 colormapped = false;
5325
5326         if (colormapped)
5327         {
5328                 if (!skinframe->qgeneratebase)
5329                         return;
5330         }
5331         else
5332         {
5333                 if (!skinframe->qgeneratemerged)
5334                         return;
5335         }
5336
5337         width = skinframe->qwidth;
5338         height = skinframe->qheight;
5339         skindata = skinframe->qpixels;
5340
5341         if (skinframe->qgeneratenmap)
5342         {
5343                 unsigned char *temp1, *temp2;
5344                 skinframe->qgeneratenmap = false;
5345                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5346                 temp2 = temp1 + width * height * 4;
5347                 // use either a custom palette or the quake palette
5348                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5349                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5350                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5351                 Mem_Free(temp1);
5352         }
5353
5354         if (skinframe->qgenerateglow)
5355         {
5356                 skinframe->qgenerateglow = false;
5357                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5358         }
5359
5360         if (colormapped)
5361         {
5362                 skinframe->qgeneratebase = false;
5363                 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);
5364                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5365                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5366         }
5367         else
5368         {
5369                 skinframe->qgeneratemerged = false;
5370                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5371         }
5372
5373         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5374         {
5375                 Mem_Free(skinframe->qpixels);
5376                 skinframe->qpixels = NULL;
5377         }
5378 }
5379
5380 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)
5381 {
5382         int i;
5383         skinframe_t *skinframe;
5384
5385         if (cls.state == ca_dedicated)
5386                 return NULL;
5387
5388         // if already loaded just return it, otherwise make a new skinframe
5389         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5390         if (skinframe && skinframe->base)
5391                 return skinframe;
5392
5393         skinframe->stain = NULL;
5394         skinframe->merged = NULL;
5395         skinframe->base = NULL;
5396         skinframe->pants = NULL;
5397         skinframe->shirt = NULL;
5398         skinframe->nmap = NULL;
5399         skinframe->gloss = NULL;
5400         skinframe->glow = NULL;
5401         skinframe->fog = NULL;
5402         skinframe->hasalpha = false;
5403
5404         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5405         if (!skindata)
5406                 return NULL;
5407
5408         if (developer_loading.integer)
5409                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5410
5411         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5412         if (textureflags & TEXF_ALPHA)
5413         {
5414                 for (i = 0;i < width * height;i++)
5415                 {
5416                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5417                         {
5418                                 skinframe->hasalpha = true;
5419                                 break;
5420                         }
5421                 }
5422                 if (r_loadfog && skinframe->hasalpha)
5423                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5424         }
5425
5426         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5427         //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]);
5428
5429         return skinframe;
5430 }
5431
5432 skinframe_t *R_SkinFrame_LoadMissing(void)
5433 {
5434         skinframe_t *skinframe;
5435
5436         if (cls.state == ca_dedicated)
5437                 return NULL;
5438
5439         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5440         skinframe->stain = NULL;
5441         skinframe->merged = NULL;
5442         skinframe->base = NULL;
5443         skinframe->pants = NULL;
5444         skinframe->shirt = NULL;
5445         skinframe->nmap = NULL;
5446         skinframe->gloss = NULL;
5447         skinframe->glow = NULL;
5448         skinframe->fog = NULL;
5449         skinframe->hasalpha = false;
5450
5451         skinframe->avgcolor[0] = rand() / RAND_MAX;
5452         skinframe->avgcolor[1] = rand() / RAND_MAX;
5453         skinframe->avgcolor[2] = rand() / RAND_MAX;
5454         skinframe->avgcolor[3] = 1;
5455
5456         return skinframe;
5457 }
5458
5459 void R_Main_FreeViewCache(void)
5460 {
5461         if (r_refdef.viewcache.entityvisible)
5462                 Mem_Free(r_refdef.viewcache.entityvisible);
5463         if (r_refdef.viewcache.world_pvsbits)
5464                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5465         if (r_refdef.viewcache.world_leafvisible)
5466                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5467         if (r_refdef.viewcache.world_surfacevisible)
5468                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5469         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5470 }
5471
5472 void R_Main_ResizeViewCache(void)
5473 {
5474         int numentities = r_refdef.scene.numentities;
5475         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5476         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5477         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5478         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5479         if (r_refdef.viewcache.maxentities < numentities)
5480         {
5481                 r_refdef.viewcache.maxentities = numentities;
5482                 if (r_refdef.viewcache.entityvisible)
5483                         Mem_Free(r_refdef.viewcache.entityvisible);
5484                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5485         }
5486         if (r_refdef.viewcache.world_numclusters != numclusters)
5487         {
5488                 r_refdef.viewcache.world_numclusters = numclusters;
5489                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5490                 if (r_refdef.viewcache.world_pvsbits)
5491                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5492                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5493         }
5494         if (r_refdef.viewcache.world_numleafs != numleafs)
5495         {
5496                 r_refdef.viewcache.world_numleafs = numleafs;
5497                 if (r_refdef.viewcache.world_leafvisible)
5498                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5499                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5500         }
5501         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5502         {
5503                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5504                 if (r_refdef.viewcache.world_surfacevisible)
5505                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5506                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5507         }
5508 }
5509
5510 extern rtexture_t *loadingscreentexture;
5511 void gl_main_start(void)
5512 {
5513         loadingscreentexture = NULL;
5514         r_texture_blanknormalmap = NULL;
5515         r_texture_white = NULL;
5516         r_texture_grey128 = NULL;
5517         r_texture_black = NULL;
5518         r_texture_whitecube = NULL;
5519         r_texture_normalizationcube = NULL;
5520         r_texture_fogattenuation = NULL;
5521         r_texture_gammaramps = NULL;
5522
5523         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5524         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5525
5526         switch(vid.renderpath)
5527         {
5528         case RENDERPATH_GL20:
5529         case RENDERPATH_CGGL:
5530                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5531                 Cvar_SetValueQuick(&gl_combine, 1);
5532                 Cvar_SetValueQuick(&r_glsl, 1);
5533                 r_loadnormalmap = true;
5534                 r_loadgloss = true;
5535                 r_loadfog = false;
5536                 break;
5537         case RENDERPATH_GL13:
5538                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5539                 Cvar_SetValueQuick(&gl_combine, 1);
5540                 Cvar_SetValueQuick(&r_glsl, 0);
5541                 r_loadnormalmap = false;
5542                 r_loadgloss = false;
5543                 r_loadfog = true;
5544                 break;
5545         case RENDERPATH_GL11:
5546                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5547                 Cvar_SetValueQuick(&gl_combine, 0);
5548                 Cvar_SetValueQuick(&r_glsl, 0);
5549                 r_loadnormalmap = false;
5550                 r_loadgloss = false;
5551                 r_loadfog = true;
5552                 break;
5553         }
5554
5555         R_AnimCache_Free();
5556         R_FrameData_Reset();
5557
5558         r_numqueries = 0;
5559         r_maxqueries = 0;
5560         memset(r_queries, 0, sizeof(r_queries));
5561
5562         r_qwskincache = NULL;
5563         r_qwskincache_size = 0;
5564
5565         // set up r_skinframe loading system for textures
5566         memset(&r_skinframe, 0, sizeof(r_skinframe));
5567         r_skinframe.loadsequence = 1;
5568         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5569
5570         r_main_texturepool = R_AllocTexturePool();
5571         R_BuildBlankTextures();
5572         R_BuildNoTexture();
5573         if (vid.support.arb_texture_cube_map)
5574         {
5575                 R_BuildWhiteCube();
5576                 R_BuildNormalizationCube();
5577         }
5578         r_texture_fogattenuation = NULL;
5579         r_texture_gammaramps = NULL;
5580         //r_texture_fogintensity = NULL;
5581         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5582         memset(&r_waterstate, 0, sizeof(r_waterstate));
5583         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5584         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5585 #ifdef SUPPORTCG
5586         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5587         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5588 #endif
5589         memset(&r_svbsp, 0, sizeof (r_svbsp));
5590
5591         r_refdef.fogmasktable_density = 0;
5592 }
5593
5594 void gl_main_shutdown(void)
5595 {
5596         R_AnimCache_Free();
5597         R_FrameData_Reset();
5598
5599         R_Main_FreeViewCache();
5600
5601         if (r_maxqueries)
5602                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5603
5604         r_numqueries = 0;
5605         r_maxqueries = 0;
5606         memset(r_queries, 0, sizeof(r_queries));
5607
5608         r_qwskincache = NULL;
5609         r_qwskincache_size = 0;
5610
5611         // clear out the r_skinframe state
5612         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5613         memset(&r_skinframe, 0, sizeof(r_skinframe));
5614
5615         if (r_svbsp.nodes)
5616                 Mem_Free(r_svbsp.nodes);
5617         memset(&r_svbsp, 0, sizeof (r_svbsp));
5618         R_FreeTexturePool(&r_main_texturepool);
5619         loadingscreentexture = NULL;
5620         r_texture_blanknormalmap = NULL;
5621         r_texture_white = NULL;
5622         r_texture_grey128 = NULL;
5623         r_texture_black = NULL;
5624         r_texture_whitecube = NULL;
5625         r_texture_normalizationcube = NULL;
5626         r_texture_fogattenuation = NULL;
5627         r_texture_gammaramps = NULL;
5628         //r_texture_fogintensity = NULL;
5629         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5630         memset(&r_waterstate, 0, sizeof(r_waterstate));
5631         R_GLSL_Restart_f();
5632 }
5633
5634 extern void CL_ParseEntityLump(char *entitystring);
5635 void gl_main_newmap(void)
5636 {
5637         // FIXME: move this code to client
5638         int l;
5639         char *entities, entname[MAX_QPATH];
5640         if (r_qwskincache)
5641                 Mem_Free(r_qwskincache);
5642         r_qwskincache = NULL;
5643         r_qwskincache_size = 0;
5644         if (cl.worldmodel)
5645         {
5646                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5647                 l = (int)strlen(entname) - 4;
5648                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5649                 {
5650                         memcpy(entname + l, ".ent", 5);
5651                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5652                         {
5653                                 CL_ParseEntityLump(entities);
5654                                 Mem_Free(entities);
5655                                 return;
5656                         }
5657                 }
5658                 if (cl.worldmodel->brush.entities)
5659                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5660         }
5661         R_Main_FreeViewCache();
5662
5663         R_FrameData_Reset();
5664 }
5665
5666 void GL_Main_Init(void)
5667 {
5668         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5669
5670         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5671         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5672         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5673         if (gamemode == GAME_NEHAHRA)
5674         {
5675                 Cvar_RegisterVariable (&gl_fogenable);
5676                 Cvar_RegisterVariable (&gl_fogdensity);
5677                 Cvar_RegisterVariable (&gl_fogred);
5678                 Cvar_RegisterVariable (&gl_foggreen);
5679                 Cvar_RegisterVariable (&gl_fogblue);
5680                 Cvar_RegisterVariable (&gl_fogstart);
5681                 Cvar_RegisterVariable (&gl_fogend);
5682                 Cvar_RegisterVariable (&gl_skyclip);
5683         }
5684         Cvar_RegisterVariable(&r_motionblur);
5685         Cvar_RegisterVariable(&r_motionblur_maxblur);
5686         Cvar_RegisterVariable(&r_motionblur_bmin);
5687         Cvar_RegisterVariable(&r_motionblur_vmin);
5688         Cvar_RegisterVariable(&r_motionblur_vmax);
5689         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5690         Cvar_RegisterVariable(&r_motionblur_randomize);
5691         Cvar_RegisterVariable(&r_damageblur);
5692         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5693         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5694         Cvar_RegisterVariable(&r_equalize_entities_by);
5695         Cvar_RegisterVariable(&r_equalize_entities_to);
5696         Cvar_RegisterVariable(&r_depthfirst);
5697         Cvar_RegisterVariable(&r_useinfinitefarclip);
5698         Cvar_RegisterVariable(&r_farclip_base);
5699         Cvar_RegisterVariable(&r_farclip_world);
5700         Cvar_RegisterVariable(&r_nearclip);
5701         Cvar_RegisterVariable(&r_showbboxes);
5702         Cvar_RegisterVariable(&r_showsurfaces);
5703         Cvar_RegisterVariable(&r_showtris);
5704         Cvar_RegisterVariable(&r_shownormals);
5705         Cvar_RegisterVariable(&r_showlighting);
5706         Cvar_RegisterVariable(&r_showshadowvolumes);
5707         Cvar_RegisterVariable(&r_showcollisionbrushes);
5708         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5709         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5710         Cvar_RegisterVariable(&r_showdisabledepthtest);
5711         Cvar_RegisterVariable(&r_drawportals);
5712         Cvar_RegisterVariable(&r_drawentities);
5713         Cvar_RegisterVariable(&r_cullentities_trace);
5714         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5715         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5716         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5717         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5718         Cvar_RegisterVariable(&r_drawviewmodel);
5719         Cvar_RegisterVariable(&r_speeds);
5720         Cvar_RegisterVariable(&r_fullbrights);
5721         Cvar_RegisterVariable(&r_wateralpha);
5722         Cvar_RegisterVariable(&r_dynamic);
5723         Cvar_RegisterVariable(&r_fullbright);
5724         Cvar_RegisterVariable(&r_shadows);
5725         Cvar_RegisterVariable(&r_shadows_darken);
5726         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5727         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5728         Cvar_RegisterVariable(&r_shadows_throwdistance);
5729         Cvar_RegisterVariable(&r_shadows_throwdirection);
5730         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5731         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5732         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5733         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5734         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5735         Cvar_RegisterVariable(&r_fog_exp2);
5736         Cvar_RegisterVariable(&r_drawfog);
5737         Cvar_RegisterVariable(&r_transparentdepthmasking);
5738         Cvar_RegisterVariable(&r_texture_dds_load);
5739         Cvar_RegisterVariable(&r_texture_dds_save);
5740         Cvar_RegisterVariable(&r_textureunits);
5741         Cvar_RegisterVariable(&gl_combine);
5742         Cvar_RegisterVariable(&r_glsl);
5743         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5744         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5745         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5746         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5747         Cvar_RegisterVariable(&r_glsl_postprocess);
5748         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5749         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5750         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5751         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5752         Cvar_RegisterVariable(&r_water);
5753         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5754         Cvar_RegisterVariable(&r_water_clippingplanebias);
5755         Cvar_RegisterVariable(&r_water_refractdistort);
5756         Cvar_RegisterVariable(&r_water_reflectdistort);
5757         Cvar_RegisterVariable(&r_lerpsprites);
5758         Cvar_RegisterVariable(&r_lerpmodels);
5759         Cvar_RegisterVariable(&r_lerplightstyles);
5760         Cvar_RegisterVariable(&r_waterscroll);
5761         Cvar_RegisterVariable(&r_bloom);
5762         Cvar_RegisterVariable(&r_bloom_colorscale);
5763         Cvar_RegisterVariable(&r_bloom_brighten);
5764         Cvar_RegisterVariable(&r_bloom_blur);
5765         Cvar_RegisterVariable(&r_bloom_resolution);
5766         Cvar_RegisterVariable(&r_bloom_colorexponent);
5767         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5768         Cvar_RegisterVariable(&r_hdr);
5769         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5770         Cvar_RegisterVariable(&r_hdr_glowintensity);
5771         Cvar_RegisterVariable(&r_hdr_range);
5772         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5773         Cvar_RegisterVariable(&developer_texturelogging);
5774         Cvar_RegisterVariable(&gl_lightmaps);
5775         Cvar_RegisterVariable(&r_test);
5776         Cvar_RegisterVariable(&r_batchmode);
5777         Cvar_RegisterVariable(&r_glsl_saturation);
5778         Cvar_RegisterVariable(&r_framedatasize);
5779         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5780                 Cvar_SetValue("r_fullbrights", 0);
5781         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5782
5783         Cvar_RegisterVariable(&r_track_sprites);
5784         Cvar_RegisterVariable(&r_track_sprites_flags);
5785         Cvar_RegisterVariable(&r_track_sprites_scalew);
5786         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5787 }
5788
5789 extern void R_Textures_Init(void);
5790 extern void GL_Draw_Init(void);
5791 extern void GL_Main_Init(void);
5792 extern void R_Shadow_Init(void);
5793 extern void R_Sky_Init(void);
5794 extern void GL_Surf_Init(void);
5795 extern void R_Particles_Init(void);
5796 extern void R_Explosion_Init(void);
5797 extern void gl_backend_init(void);
5798 extern void Sbar_Init(void);
5799 extern void R_LightningBeams_Init(void);
5800 extern void Mod_RenderInit(void);
5801 extern void Font_Init(void);
5802
5803 void Render_Init(void)
5804 {
5805         gl_backend_init();
5806         R_Textures_Init();
5807         GL_Main_Init();
5808         Font_Init();
5809         GL_Draw_Init();
5810         R_Shadow_Init();
5811         R_Sky_Init();
5812         GL_Surf_Init();
5813         Sbar_Init();
5814         R_Particles_Init();
5815         R_Explosion_Init();
5816         R_LightningBeams_Init();
5817         Mod_RenderInit();
5818 }
5819
5820 /*
5821 ===============
5822 GL_Init
5823 ===============
5824 */
5825 extern char *ENGINE_EXTENSIONS;
5826 void GL_Init (void)
5827 {
5828         gl_renderer = (const char *)qglGetString(GL_RENDERER);
5829         gl_vendor = (const char *)qglGetString(GL_VENDOR);
5830         gl_version = (const char *)qglGetString(GL_VERSION);
5831         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5832
5833         if (!gl_extensions)
5834                 gl_extensions = "";
5835         if (!gl_platformextensions)
5836                 gl_platformextensions = "";
5837
5838         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5839         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5840         Con_Printf("GL_VERSION: %s\n", gl_version);
5841         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
5842         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
5843
5844         VID_CheckExtensions();
5845
5846         // LordHavoc: report supported extensions
5847         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
5848
5849         // clear to black (loading plaque will be seen over this)
5850         CHECKGLERROR
5851         qglClearColor(0,0,0,1);CHECKGLERROR
5852         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
5853 }
5854
5855 int R_CullBox(const vec3_t mins, const vec3_t maxs)
5856 {
5857         int i;
5858         mplane_t *p;
5859         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5860         {
5861                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
5862                 if (i == 4)
5863                         continue;
5864                 p = r_refdef.view.frustum + i;
5865                 switch(p->signbits)
5866                 {
5867                 default:
5868                 case 0:
5869                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5870                                 return true;
5871                         break;
5872                 case 1:
5873                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5874                                 return true;
5875                         break;
5876                 case 2:
5877                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5878                                 return true;
5879                         break;
5880                 case 3:
5881                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5882                                 return true;
5883                         break;
5884                 case 4:
5885                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5886                                 return true;
5887                         break;
5888                 case 5:
5889                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5890                                 return true;
5891                         break;
5892                 case 6:
5893                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5894                                 return true;
5895                         break;
5896                 case 7:
5897                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5898                                 return true;
5899                         break;
5900                 }
5901         }
5902         return false;
5903 }
5904
5905 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
5906 {
5907         int i;
5908         const mplane_t *p;
5909         for (i = 0;i < numplanes;i++)
5910         {
5911                 p = planes + i;
5912                 switch(p->signbits)
5913                 {
5914                 default:
5915                 case 0:
5916                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5917                                 return true;
5918                         break;
5919                 case 1:
5920                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5921                                 return true;
5922                         break;
5923                 case 2:
5924                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5925                                 return true;
5926                         break;
5927                 case 3:
5928                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5929                                 return true;
5930                         break;
5931                 case 4:
5932                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5933                                 return true;
5934                         break;
5935                 case 5:
5936                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5937                                 return true;
5938                         break;
5939                 case 6:
5940                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5941                                 return true;
5942                         break;
5943                 case 7:
5944                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5945                                 return true;
5946                         break;
5947                 }
5948         }
5949         return false;
5950 }
5951
5952 //==================================================================================
5953
5954 // LordHavoc: this stores temporary data used within the same frame
5955
5956 qboolean r_framedata_failed;
5957 static size_t r_framedata_size;
5958 static size_t r_framedata_current;
5959 static void *r_framedata_base;
5960
5961 void R_FrameData_Reset(void)
5962 {
5963         if (r_framedata_base)
5964                 Mem_Free(r_framedata_base);
5965         r_framedata_base = NULL;
5966         r_framedata_size = 0;
5967         r_framedata_current = 0;
5968         r_framedata_failed = false;
5969 }
5970
5971 void R_FrameData_NewFrame(void)
5972 {
5973         size_t wantedsize;
5974         if (r_framedata_failed)
5975                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
5976         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
5977         wantedsize = bound(65536, wantedsize, 128*1024*1024);
5978         if (r_framedata_size != wantedsize)
5979         {
5980                 r_framedata_size = wantedsize;
5981                 if (r_framedata_base)
5982                         Mem_Free(r_framedata_base);
5983                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
5984         }
5985         r_framedata_current = 0;
5986         r_framedata_failed = false;
5987 }
5988
5989 void *R_FrameData_Alloc(size_t size)
5990 {
5991         void *data;
5992
5993         // align to 16 byte boundary
5994         size = (size + 15) & ~15;
5995         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
5996         r_framedata_current += size;
5997
5998         // check overflow
5999         if (r_framedata_current > r_framedata_size)
6000                 r_framedata_failed = true;
6001
6002         // return NULL on everything after a failure
6003         if (r_framedata_failed)
6004                 return NULL;
6005
6006         return data;
6007 }
6008
6009 void *R_FrameData_Store(size_t size, void *data)
6010 {
6011         void *d = R_FrameData_Alloc(size);
6012         if (d)
6013                 memcpy(d, data, size);
6014         return d;
6015 }
6016
6017 //==================================================================================
6018
6019 // LordHavoc: animcache originally written by Echon, rewritten since then
6020
6021 /**
6022  * Animation cache prevents re-generating mesh data for an animated model
6023  * multiple times in one frame for lighting, shadowing, reflections, etc.
6024  */
6025
6026 void R_AnimCache_Free(void)
6027 {
6028 }
6029
6030 void R_AnimCache_ClearCache(void)
6031 {
6032         int i;
6033         entity_render_t *ent;
6034
6035         for (i = 0;i < r_refdef.scene.numentities;i++)
6036         {
6037                 ent = r_refdef.scene.entities[i];
6038                 ent->animcache_vertex3f = NULL;
6039                 ent->animcache_normal3f = NULL;
6040                 ent->animcache_svector3f = NULL;
6041                 ent->animcache_tvector3f = NULL;
6042         }
6043 }
6044
6045 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6046 {
6047         dp_model_t *model = ent->model;
6048         int numvertices;
6049         // see if it's already cached this frame
6050         if (ent->animcache_vertex3f)
6051         {
6052                 // add normals/tangents if needed
6053                 if (wantnormals || wanttangents)
6054                 {
6055                         if (ent->animcache_normal3f)
6056                                 wantnormals = false;
6057                         if (ent->animcache_svector3f)
6058                                 wanttangents = false;
6059                         if (wantnormals || wanttangents)
6060                         {
6061                                 numvertices = model->surfmesh.num_vertices;
6062                                 if (wantnormals)
6063                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6064                                 if (wanttangents)
6065                                 {
6066                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6067                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6068                                 }
6069                                 if (!r_framedata_failed)
6070                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6071                         }
6072                 }
6073         }
6074         else
6075         {
6076                 // see if this ent is worth caching
6077                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6078                         return false;
6079                 // get some memory for this entity and generate mesh data
6080                 numvertices = model->surfmesh.num_vertices;
6081                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6082                 if (wantnormals)
6083                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6084                 if (wanttangents)
6085                 {
6086                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6087                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6088                 }
6089                 if (!r_framedata_failed)
6090                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6091         }
6092         return !r_framedata_failed;
6093 }
6094
6095 void R_AnimCache_CacheVisibleEntities(void)
6096 {
6097         int i;
6098         qboolean wantnormals = !r_showsurfaces.integer;
6099         qboolean wanttangents = !r_showsurfaces.integer;
6100
6101         switch(vid.renderpath)
6102         {
6103         case RENDERPATH_GL20:
6104         case RENDERPATH_CGGL:
6105                 break;
6106         case RENDERPATH_GL13:
6107         case RENDERPATH_GL11:
6108                 wanttangents = false;
6109                 break;
6110         }
6111
6112         // TODO: thread this
6113         // NOTE: R_PrepareRTLights() also caches entities
6114
6115         for (i = 0;i < r_refdef.scene.numentities;i++)
6116                 if (r_refdef.viewcache.entityvisible[i])
6117                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6118
6119         if (r_shadows.integer)
6120                 for (i = 0;i < r_refdef.scene.numentities;i++)
6121                         if (!r_refdef.viewcache.entityvisible[i])
6122                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6123 }
6124
6125 //==================================================================================
6126
6127 static void R_View_UpdateEntityLighting (void)
6128 {
6129         int i;
6130         entity_render_t *ent;
6131         vec3_t tempdiffusenormal, avg;
6132         vec_t f, fa, fd, fdd;
6133
6134         for (i = 0;i < r_refdef.scene.numentities;i++)
6135         {
6136                 ent = r_refdef.scene.entities[i];
6137
6138                 // skip unseen models
6139                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6140                         continue;
6141
6142                 // skip bsp models
6143                 if (ent->model && ent->model->brush.num_leafs)
6144                 {
6145                         // TODO: use modellight for r_ambient settings on world?
6146                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6147                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6148                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6149                         continue;
6150                 }
6151
6152                 // fetch the lighting from the worldmodel data
6153                 VectorClear(ent->modellight_ambient);
6154                 VectorClear(ent->modellight_diffuse);
6155                 VectorClear(tempdiffusenormal);
6156                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6157                 {
6158                         vec3_t org;
6159                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6160                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6161                         if(ent->flags & RENDER_EQUALIZE)
6162                         {
6163                                 // first fix up ambient lighting...
6164                                 if(r_equalize_entities_minambient.value > 0)
6165                                 {
6166                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6167                                         if(fd > 0)
6168                                         {
6169                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6170                                                 if(fa < r_equalize_entities_minambient.value * fd)
6171                                                 {
6172                                                         // solve:
6173                                                         //   fa'/fd' = minambient
6174                                                         //   fa'+0.25*fd' = fa+0.25*fd
6175                                                         //   ...
6176                                                         //   fa' = fd' * minambient
6177                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6178                                                         //   ...
6179                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6180                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6181                                                         //   ...
6182                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6183                                                         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
6184                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6185                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6186                                                 }
6187                                         }
6188                                 }
6189
6190                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6191                                 {
6192                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6193                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6194                                         if(f > 0)
6195                                         {
6196                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6197                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6198                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6199                                         }
6200                                 }
6201                         }
6202                 }
6203                 else // highly rare
6204                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6205
6206                 // move the light direction into modelspace coordinates for lighting code
6207                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6208                 if(VectorLength2(ent->modellight_lightdir) == 0)
6209                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6210                 VectorNormalize(ent->modellight_lightdir);
6211         }
6212 }
6213
6214 #define MAX_LINEOFSIGHTTRACES 64
6215
6216 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6217 {
6218         int i;
6219         vec3_t boxmins, boxmaxs;
6220         vec3_t start;
6221         vec3_t end;
6222         dp_model_t *model = r_refdef.scene.worldmodel;
6223
6224         if (!model || !model->brush.TraceLineOfSight)
6225                 return true;
6226
6227         // expand the box a little
6228         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6229         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6230         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6231         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6232         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6233         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6234
6235         // try center
6236         VectorCopy(eye, start);
6237         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6238         if (model->brush.TraceLineOfSight(model, start, end))
6239                 return true;
6240
6241         // try various random positions
6242         for (i = 0;i < numsamples;i++)
6243         {
6244                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6245                 if (model->brush.TraceLineOfSight(model, start, end))
6246                         return true;
6247         }
6248
6249         return false;
6250 }
6251
6252
6253 static void R_View_UpdateEntityVisible (void)
6254 {
6255         int i;
6256         int renderimask;
6257         int samples;
6258         entity_render_t *ent;
6259
6260         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6261         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6262         {
6263                 // worldmodel can check visibility
6264                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6265                 for (i = 0;i < r_refdef.scene.numentities;i++)
6266                 {
6267                         ent = r_refdef.scene.entities[i];
6268                         if (!(ent->flags & renderimask))
6269                         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)))
6270                         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))
6271                                 r_refdef.viewcache.entityvisible[i] = true;
6272                 }
6273                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6274                 {
6275                         for (i = 0;i < r_refdef.scene.numentities;i++)
6276                         {
6277                                 ent = r_refdef.scene.entities[i];
6278                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6279                                 {
6280                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6281                                         if (samples < 0)
6282                                                 continue; // temp entities do pvs only
6283                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6284                                                 ent->last_trace_visibility = realtime;
6285                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6286                                                 r_refdef.viewcache.entityvisible[i] = 0;
6287                                 }
6288                         }
6289                 }
6290         }
6291         else
6292         {
6293                 // no worldmodel or it can't check visibility
6294                 for (i = 0;i < r_refdef.scene.numentities;i++)
6295                 {
6296                         ent = r_refdef.scene.entities[i];
6297                         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));
6298                 }
6299         }
6300 }
6301
6302 /// only used if skyrendermasked, and normally returns false
6303 int R_DrawBrushModelsSky (void)
6304 {
6305         int i, sky;
6306         entity_render_t *ent;
6307
6308         sky = false;
6309         for (i = 0;i < r_refdef.scene.numentities;i++)
6310         {
6311                 if (!r_refdef.viewcache.entityvisible[i])
6312                         continue;
6313                 ent = r_refdef.scene.entities[i];
6314                 if (!ent->model || !ent->model->DrawSky)
6315                         continue;
6316                 ent->model->DrawSky(ent);
6317                 sky = true;
6318         }
6319         return sky;
6320 }
6321
6322 static void R_DrawNoModel(entity_render_t *ent);
6323 static void R_DrawModels(void)
6324 {
6325         int i;
6326         entity_render_t *ent;
6327
6328         for (i = 0;i < r_refdef.scene.numentities;i++)
6329         {
6330                 if (!r_refdef.viewcache.entityvisible[i])
6331                         continue;
6332                 ent = r_refdef.scene.entities[i];
6333                 r_refdef.stats.entities++;
6334                 if (ent->model && ent->model->Draw != NULL)
6335                         ent->model->Draw(ent);
6336                 else
6337                         R_DrawNoModel(ent);
6338         }
6339 }
6340
6341 static void R_DrawModelsDepth(void)
6342 {
6343         int i;
6344         entity_render_t *ent;
6345
6346         for (i = 0;i < r_refdef.scene.numentities;i++)
6347         {
6348                 if (!r_refdef.viewcache.entityvisible[i])
6349                         continue;
6350                 ent = r_refdef.scene.entities[i];
6351                 if (ent->model && ent->model->DrawDepth != NULL)
6352                         ent->model->DrawDepth(ent);
6353         }
6354 }
6355
6356 static void R_DrawModelsDebug(void)
6357 {
6358         int i;
6359         entity_render_t *ent;
6360
6361         for (i = 0;i < r_refdef.scene.numentities;i++)
6362         {
6363                 if (!r_refdef.viewcache.entityvisible[i])
6364                         continue;
6365                 ent = r_refdef.scene.entities[i];
6366                 if (ent->model && ent->model->DrawDebug != NULL)
6367                         ent->model->DrawDebug(ent);
6368         }
6369 }
6370
6371 static void R_DrawModelsAddWaterPlanes(void)
6372 {
6373         int i;
6374         entity_render_t *ent;
6375
6376         for (i = 0;i < r_refdef.scene.numentities;i++)
6377         {
6378                 if (!r_refdef.viewcache.entityvisible[i])
6379                         continue;
6380                 ent = r_refdef.scene.entities[i];
6381                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6382                         ent->model->DrawAddWaterPlanes(ent);
6383         }
6384 }
6385
6386 static void R_View_SetFrustum(void)
6387 {
6388         int i;
6389         double slopex, slopey;
6390         vec3_t forward, left, up, origin;
6391
6392         // we can't trust r_refdef.view.forward and friends in reflected scenes
6393         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6394
6395 #if 0
6396         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6397         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6398         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6399         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6400         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6401         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6402         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6403         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6404         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6405         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6406         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6407         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6408 #endif
6409
6410 #if 0
6411         zNear = r_refdef.nearclip;
6412         nudge = 1.0 - 1.0 / (1<<23);
6413         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6414         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6415         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6416         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6417         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6418         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6419         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6420         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6421 #endif
6422
6423
6424
6425 #if 0
6426         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6427         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6428         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6429         r_refdef.view.frustum[0].dist = m[15] - m[12];
6430
6431         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6432         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6433         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6434         r_refdef.view.frustum[1].dist = m[15] + m[12];
6435
6436         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6437         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6438         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6439         r_refdef.view.frustum[2].dist = m[15] - m[13];
6440
6441         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6442         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6443         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6444         r_refdef.view.frustum[3].dist = m[15] + m[13];
6445
6446         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6447         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6448         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6449         r_refdef.view.frustum[4].dist = m[15] - m[14];
6450
6451         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6452         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6453         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6454         r_refdef.view.frustum[5].dist = m[15] + m[14];
6455 #endif
6456
6457         if (r_refdef.view.useperspective)
6458         {
6459                 slopex = 1.0 / r_refdef.view.frustum_x;
6460                 slopey = 1.0 / r_refdef.view.frustum_y;
6461                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6462                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6463                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6464                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6465                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6466
6467                 // Leaving those out was a mistake, those were in the old code, and they
6468                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6469                 // I couldn't reproduce it after adding those normalizations. --blub
6470                 VectorNormalize(r_refdef.view.frustum[0].normal);
6471                 VectorNormalize(r_refdef.view.frustum[1].normal);
6472                 VectorNormalize(r_refdef.view.frustum[2].normal);
6473                 VectorNormalize(r_refdef.view.frustum[3].normal);
6474
6475                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6476                 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]);
6477                 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]);
6478                 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]);
6479                 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]);
6480
6481                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6482                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6483                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6484                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6485                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6486         }
6487         else
6488         {
6489                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6490                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6491                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6492                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6493                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6494                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6495                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6496                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6497                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6498                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6499         }
6500         r_refdef.view.numfrustumplanes = 5;
6501
6502         if (r_refdef.view.useclipplane)
6503         {
6504                 r_refdef.view.numfrustumplanes = 6;
6505                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6506         }
6507
6508         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6509                 PlaneClassify(r_refdef.view.frustum + i);
6510
6511         // LordHavoc: note to all quake engine coders, Quake had a special case
6512         // for 90 degrees which assumed a square view (wrong), so I removed it,
6513         // Quake2 has it disabled as well.
6514
6515         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6516         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6517         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6518         //PlaneClassify(&frustum[0]);
6519
6520         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6521         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6522         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6523         //PlaneClassify(&frustum[1]);
6524
6525         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6526         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6527         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6528         //PlaneClassify(&frustum[2]);
6529
6530         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6531         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6532         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6533         //PlaneClassify(&frustum[3]);
6534
6535         // nearclip plane
6536         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6537         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6538         //PlaneClassify(&frustum[4]);
6539 }
6540
6541 void R_View_Update(void)
6542 {
6543         R_Main_ResizeViewCache();
6544         R_View_SetFrustum();
6545         R_View_WorldVisibility(r_refdef.view.useclipplane);
6546         R_View_UpdateEntityVisible();
6547         R_View_UpdateEntityLighting();
6548 }
6549
6550 void R_SetupView(qboolean allowwaterclippingplane)
6551 {
6552         const float *customclipplane = NULL;
6553         float plane[4];
6554         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6555         {
6556                 // LordHavoc: couldn't figure out how to make this approach the
6557                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6558                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6559                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6560                         dist = r_refdef.view.clipplane.dist;
6561                 plane[0] = r_refdef.view.clipplane.normal[0];
6562                 plane[1] = r_refdef.view.clipplane.normal[1];
6563                 plane[2] = r_refdef.view.clipplane.normal[2];
6564                 plane[3] = dist;
6565                 customclipplane = plane;
6566         }
6567
6568         if (!r_refdef.view.useperspective)
6569                 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);
6570         else if (vid.stencil && r_useinfinitefarclip.integer)
6571                 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);
6572         else
6573                 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);
6574         R_SetViewport(&r_refdef.view.viewport);
6575 }
6576
6577 void R_EntityMatrix(const matrix4x4_t *matrix)
6578 {
6579         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6580         {
6581                 gl_modelmatrixchanged = false;
6582                 gl_modelmatrix = *matrix;
6583                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6584                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6585                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6586                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6587                 CHECKGLERROR
6588                 switch(vid.renderpath)
6589                 {
6590                 case RENDERPATH_GL20:
6591                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6592                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6593                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6594                         break;
6595                 case RENDERPATH_CGGL:
6596 #ifdef SUPPORTCG
6597                         CHECKCGERROR
6598                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6599                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6600                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6601 #endif
6602                         break;
6603                 case RENDERPATH_GL13:
6604                 case RENDERPATH_GL11:
6605                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6606                         break;
6607                 }
6608         }
6609 }
6610
6611 void R_ResetViewRendering2D(void)
6612 {
6613         r_viewport_t viewport;
6614         DrawQ_Finish();
6615
6616         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6617         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);
6618         R_SetViewport(&viewport);
6619         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6620         GL_Color(1, 1, 1, 1);
6621         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6622         GL_BlendFunc(GL_ONE, GL_ZERO);
6623         GL_AlphaTest(false);
6624         GL_ScissorTest(false);
6625         GL_DepthMask(false);
6626         GL_DepthRange(0, 1);
6627         GL_DepthTest(false);
6628         R_EntityMatrix(&identitymatrix);
6629         R_Mesh_ResetTextureState();
6630         GL_PolygonOffset(0, 0);
6631         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6632         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6633         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6634         qglStencilMask(~0);CHECKGLERROR
6635         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6636         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6637         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6638 }
6639
6640 void R_ResetViewRendering3D(void)
6641 {
6642         DrawQ_Finish();
6643
6644         R_SetupView(true);
6645         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6646         GL_Color(1, 1, 1, 1);
6647         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6648         GL_BlendFunc(GL_ONE, GL_ZERO);
6649         GL_AlphaTest(false);
6650         GL_ScissorTest(true);
6651         GL_DepthMask(true);
6652         GL_DepthRange(0, 1);
6653         GL_DepthTest(true);
6654         R_EntityMatrix(&identitymatrix);
6655         R_Mesh_ResetTextureState();
6656         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6657         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6658         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6659         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6660         qglStencilMask(~0);CHECKGLERROR
6661         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6662         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6663         GL_CullFace(r_refdef.view.cullface_back);
6664 }
6665
6666 void R_RenderScene(void);
6667 void R_RenderWaterPlanes(void);
6668
6669 static void R_Water_StartFrame(void)
6670 {
6671         int i;
6672         int waterwidth, waterheight, texturewidth, textureheight;
6673         r_waterstate_waterplane_t *p;
6674
6675         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6676                 return;
6677
6678         switch(vid.renderpath)
6679         {
6680         case RENDERPATH_GL20:
6681         case RENDERPATH_CGGL:
6682                 break;
6683         case RENDERPATH_GL13:
6684         case RENDERPATH_GL11:
6685                 return;
6686         }
6687
6688         // set waterwidth and waterheight to the water resolution that will be
6689         // used (often less than the screen resolution for faster rendering)
6690         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6691         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6692
6693         // calculate desired texture sizes
6694         // can't use water if the card does not support the texture size
6695         if (!r_water.integer || r_showsurfaces.integer)
6696                 texturewidth = textureheight = waterwidth = waterheight = 0;
6697         else if (vid.support.arb_texture_non_power_of_two)
6698         {
6699                 texturewidth = waterwidth;
6700                 textureheight = waterheight;
6701         }
6702         else
6703         {
6704                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6705                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6706         }
6707
6708         // allocate textures as needed
6709         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6710         {
6711                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6712                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6713                 {
6714                         if (p->texture_refraction)
6715                                 R_FreeTexture(p->texture_refraction);
6716                         p->texture_refraction = NULL;
6717                         if (p->texture_reflection)
6718                                 R_FreeTexture(p->texture_reflection);
6719                         p->texture_reflection = NULL;
6720                 }
6721                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6722                 r_waterstate.texturewidth = texturewidth;
6723                 r_waterstate.textureheight = textureheight;
6724         }
6725
6726         if (r_waterstate.texturewidth)
6727         {
6728                 r_waterstate.enabled = true;
6729
6730                 // when doing a reduced render (HDR) we want to use a smaller area
6731                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6732                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6733
6734                 // set up variables that will be used in shader setup
6735                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6736                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6737                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6738                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6739         }
6740
6741         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6742         r_waterstate.numwaterplanes = 0;
6743 }
6744
6745 void R_Water_AddWaterPlane(msurface_t *surface)
6746 {
6747         int triangleindex, planeindex;
6748         const int *e;
6749         vec3_t vert[3];
6750         vec3_t normal;
6751         vec3_t center;
6752         mplane_t plane;
6753         r_waterstate_waterplane_t *p;
6754         texture_t *t = R_GetCurrentTexture(surface->texture);
6755         // just use the first triangle with a valid normal for any decisions
6756         VectorClear(normal);
6757         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6758         {
6759                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6760                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6761                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6762                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6763                 if (VectorLength2(normal) >= 0.001)
6764                         break;
6765         }
6766
6767         VectorCopy(normal, plane.normal);
6768         VectorNormalize(plane.normal);
6769         plane.dist = DotProduct(vert[0], plane.normal);
6770         PlaneClassify(&plane);
6771         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6772         {
6773                 // skip backfaces (except if nocullface is set)
6774                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6775                         return;
6776                 VectorNegate(plane.normal, plane.normal);
6777                 plane.dist *= -1;
6778                 PlaneClassify(&plane);
6779         }
6780
6781
6782         // find a matching plane if there is one
6783         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6784                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6785                         break;
6786         if (planeindex >= r_waterstate.maxwaterplanes)
6787                 return; // nothing we can do, out of planes
6788
6789         // if this triangle does not fit any known plane rendered this frame, add one
6790         if (planeindex >= r_waterstate.numwaterplanes)
6791         {
6792                 // store the new plane
6793                 r_waterstate.numwaterplanes++;
6794                 p->plane = plane;
6795                 // clear materialflags and pvs
6796                 p->materialflags = 0;
6797                 p->pvsvalid = false;
6798         }
6799         // merge this surface's materialflags into the waterplane
6800         p->materialflags |= t->currentmaterialflags;
6801         // merge this surface's PVS into the waterplane
6802         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6803         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6804          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6805         {
6806                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6807                 p->pvsvalid = true;
6808         }
6809 }
6810
6811 static void R_Water_ProcessPlanes(void)
6812 {
6813         r_refdef_view_t originalview;
6814         r_refdef_view_t myview;
6815         int planeindex;
6816         r_waterstate_waterplane_t *p;
6817
6818         originalview = r_refdef.view;
6819
6820         // make sure enough textures are allocated
6821         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6822         {
6823                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6824                 {
6825                         if (!p->texture_refraction)
6826                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6827                         if (!p->texture_refraction)
6828                                 goto error;
6829                 }
6830
6831                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6832                 {
6833                         if (!p->texture_reflection)
6834                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6835                         if (!p->texture_reflection)
6836                                 goto error;
6837                 }
6838         }
6839
6840         // render views
6841         r_refdef.view = originalview;
6842         r_refdef.view.showdebug = false;
6843         r_refdef.view.width = r_waterstate.waterwidth;
6844         r_refdef.view.height = r_waterstate.waterheight;
6845         r_refdef.view.useclipplane = true;
6846         myview = r_refdef.view;
6847         r_waterstate.renderingscene = true;
6848         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6849         {
6850                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6851                 {
6852                         r_refdef.view = myview;
6853                         // render reflected scene and copy into texture
6854                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6855                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6856                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6857                         r_refdef.view.clipplane = p->plane;
6858                         // reverse the cullface settings for this render
6859                         r_refdef.view.cullface_front = GL_FRONT;
6860                         r_refdef.view.cullface_back = GL_BACK;
6861                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6862                         {
6863                                 r_refdef.view.usecustompvs = true;
6864                                 if (p->pvsvalid)
6865                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6866                                 else
6867                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6868                         }
6869
6870                         R_ResetViewRendering3D();
6871                         R_ClearScreen(r_refdef.fogenabled);
6872                         R_View_Update();
6873                         R_RenderScene();
6874
6875                         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);
6876                 }
6877
6878                 // render the normal view scene and copy into texture
6879                 // (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)
6880                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6881                 {
6882                         r_refdef.view = myview;
6883                         r_refdef.view.clipplane = p->plane;
6884                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6885                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6886                         PlaneClassify(&r_refdef.view.clipplane);
6887
6888                         R_ResetViewRendering3D();
6889                         R_ClearScreen(r_refdef.fogenabled);
6890                         R_View_Update();
6891                         R_RenderScene();
6892
6893                         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);
6894                 }
6895
6896         }
6897         r_waterstate.renderingscene = false;
6898         r_refdef.view = originalview;
6899         R_ResetViewRendering3D();
6900         R_ClearScreen(r_refdef.fogenabled);
6901         R_View_Update();
6902         return;
6903 error:
6904         r_refdef.view = originalview;
6905         r_waterstate.renderingscene = false;
6906         Cvar_SetValueQuick(&r_water, 0);
6907         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6908         return;
6909 }
6910
6911 void R_Bloom_StartFrame(void)
6912 {
6913         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6914
6915         switch(vid.renderpath)
6916         {
6917         case RENDERPATH_GL20:
6918         case RENDERPATH_CGGL:
6919                 break;
6920         case RENDERPATH_GL13:
6921         case RENDERPATH_GL11:
6922                 return;
6923         }
6924
6925         // set bloomwidth and bloomheight to the bloom resolution that will be
6926         // used (often less than the screen resolution for faster rendering)
6927         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6928         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6929         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6930         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6931         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6932
6933         // calculate desired texture sizes
6934         if (vid.support.arb_texture_non_power_of_two)
6935         {
6936                 screentexturewidth = r_refdef.view.width;
6937                 screentextureheight = r_refdef.view.height;
6938                 bloomtexturewidth = r_bloomstate.bloomwidth;
6939                 bloomtextureheight = r_bloomstate.bloomheight;
6940         }
6941         else
6942         {
6943                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6944                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6945                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6946                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6947         }
6948
6949         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))
6950         {
6951                 Cvar_SetValueQuick(&r_hdr, 0);
6952                 Cvar_SetValueQuick(&r_bloom, 0);
6953                 Cvar_SetValueQuick(&r_motionblur, 0);
6954                 Cvar_SetValueQuick(&r_damageblur, 0);
6955         }
6956
6957         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)))
6958                 screentexturewidth = screentextureheight = 0;
6959         if (!r_hdr.integer && !r_bloom.integer)
6960                 bloomtexturewidth = bloomtextureheight = 0;
6961
6962         // allocate textures as needed
6963         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
6964         {
6965                 if (r_bloomstate.texture_screen)
6966                         R_FreeTexture(r_bloomstate.texture_screen);
6967                 r_bloomstate.texture_screen = NULL;
6968                 r_bloomstate.screentexturewidth = screentexturewidth;
6969                 r_bloomstate.screentextureheight = screentextureheight;
6970                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6971                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
6972         }
6973         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
6974         {
6975                 if (r_bloomstate.texture_bloom)
6976                         R_FreeTexture(r_bloomstate.texture_bloom);
6977                 r_bloomstate.texture_bloom = NULL;
6978                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6979                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6980                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6981                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6982         }
6983
6984         // when doing a reduced render (HDR) we want to use a smaller area
6985         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6986         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6987         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6988         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6989         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6990
6991         // set up a texcoord array for the full resolution screen image
6992         // (we have to keep this around to copy back during final render)
6993         r_bloomstate.screentexcoord2f[0] = 0;
6994         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
6995         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
6996         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
6997         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
6998         r_bloomstate.screentexcoord2f[5] = 0;
6999         r_bloomstate.screentexcoord2f[6] = 0;
7000         r_bloomstate.screentexcoord2f[7] = 0;
7001
7002         // set up a texcoord array for the reduced resolution bloom image
7003         // (which will be additive blended over the screen image)
7004         r_bloomstate.bloomtexcoord2f[0] = 0;
7005         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7006         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7007         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7008         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7009         r_bloomstate.bloomtexcoord2f[5] = 0;
7010         r_bloomstate.bloomtexcoord2f[6] = 0;
7011         r_bloomstate.bloomtexcoord2f[7] = 0;
7012
7013         if (r_hdr.integer || r_bloom.integer)
7014         {
7015                 r_bloomstate.enabled = true;
7016                 r_bloomstate.hdr = r_hdr.integer != 0;
7017         }
7018
7019         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);
7020 }
7021
7022 void R_Bloom_CopyBloomTexture(float colorscale)
7023 {
7024         r_refdef.stats.bloom++;
7025
7026         // scale down screen texture to the bloom texture size
7027         CHECKGLERROR
7028         R_SetViewport(&r_bloomstate.viewport);
7029         GL_BlendFunc(GL_ONE, GL_ZERO);
7030         GL_Color(colorscale, colorscale, colorscale, 1);
7031         // TODO: optimize with multitexture or GLSL
7032         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7033         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7034         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7035         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7036
7037         // we now have a bloom image in the framebuffer
7038         // copy it into the bloom image texture for later processing
7039         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);
7040         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7041 }
7042
7043 void R_Bloom_CopyHDRTexture(void)
7044 {
7045         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);
7046         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7047 }
7048
7049 void R_Bloom_MakeTexture(void)
7050 {
7051         int x, range, dir;
7052         float xoffset, yoffset, r, brighten;
7053
7054         r_refdef.stats.bloom++;
7055
7056         R_ResetViewRendering2D();
7057         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7058         R_Mesh_ColorPointer(NULL, 0, 0);
7059
7060         // we have a bloom image in the framebuffer
7061         CHECKGLERROR
7062         R_SetViewport(&r_bloomstate.viewport);
7063
7064         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7065         {
7066                 x *= 2;
7067                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7068                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7069                 GL_Color(r, r, r, 1);
7070                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7071                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7072                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7073                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7074
7075                 // copy the vertically blurred bloom view to a texture
7076                 GL_ActiveTexture(0);
7077                 CHECKGLERROR
7078                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7079                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7080         }
7081
7082         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7083         brighten = r_bloom_brighten.value;
7084         if (r_hdr.integer)
7085                 brighten *= r_hdr_range.value;
7086         brighten = sqrt(brighten);
7087         if(range >= 1)
7088                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7089         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7090         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7091
7092         for (dir = 0;dir < 2;dir++)
7093         {
7094                 // blend on at multiple vertical offsets to achieve a vertical blur
7095                 // TODO: do offset blends using GLSL
7096                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7097                 GL_BlendFunc(GL_ONE, GL_ZERO);
7098                 for (x = -range;x <= range;x++)
7099                 {
7100                         if (!dir){xoffset = 0;yoffset = x;}
7101                         else {xoffset = x;yoffset = 0;}
7102                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7103                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7104                         // compute a texcoord array with the specified x and y offset
7105                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7106                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7107                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7108                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7109                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7110                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7111                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7112                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7113                         // this r value looks like a 'dot' particle, fading sharply to
7114                         // black at the edges
7115                         // (probably not realistic but looks good enough)
7116                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7117                         //r = brighten/(range*2+1);
7118                         r = brighten / (range * 2 + 1);
7119                         if(range >= 1)
7120                                 r *= (1 - x*x/(float)(range*range));
7121                         GL_Color(r, r, r, 1);
7122                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7123                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7124                         GL_BlendFunc(GL_ONE, GL_ONE);
7125                 }
7126
7127                 // copy the vertically blurred bloom view to a texture
7128                 GL_ActiveTexture(0);
7129                 CHECKGLERROR
7130                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7131                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7132         }
7133
7134         // apply subtract last
7135         // (just like it would be in a GLSL shader)
7136         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7137         {
7138                 GL_BlendFunc(GL_ONE, GL_ZERO);
7139                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7140                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7141                 GL_Color(1, 1, 1, 1);
7142                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7143                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7144
7145                 GL_BlendFunc(GL_ONE, GL_ONE);
7146                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7147                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7148                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7149                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7150                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7151                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7152                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7153
7154                 // copy the darkened bloom view to a texture
7155                 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);
7156                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7157         }
7158 }
7159
7160 void R_HDR_RenderBloomTexture(void)
7161 {
7162         int oldwidth, oldheight;
7163         float oldcolorscale;
7164
7165         oldcolorscale = r_refdef.view.colorscale;
7166         oldwidth = r_refdef.view.width;
7167         oldheight = r_refdef.view.height;
7168         r_refdef.view.width = r_bloomstate.bloomwidth;
7169         r_refdef.view.height = r_bloomstate.bloomheight;
7170
7171         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7172         // TODO: add exposure compensation features
7173         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7174
7175         r_refdef.view.showdebug = false;
7176         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7177
7178         R_ResetViewRendering3D();
7179
7180         R_ClearScreen(r_refdef.fogenabled);
7181         if (r_timereport_active)
7182                 R_TimeReport("HDRclear");
7183
7184         R_View_Update();
7185         if (r_timereport_active)
7186                 R_TimeReport("visibility");
7187
7188         // only do secondary renders with HDR if r_hdr is 2 or higher
7189         r_waterstate.numwaterplanes = 0;
7190         if (r_waterstate.enabled && r_hdr.integer >= 2)
7191                 R_RenderWaterPlanes();
7192
7193         r_refdef.view.showdebug = true;
7194         R_RenderScene();
7195         r_waterstate.numwaterplanes = 0;
7196
7197         R_ResetViewRendering2D();
7198
7199         R_Bloom_CopyHDRTexture();
7200         R_Bloom_MakeTexture();
7201
7202         // restore the view settings
7203         r_refdef.view.width = oldwidth;
7204         r_refdef.view.height = oldheight;
7205         r_refdef.view.colorscale = oldcolorscale;
7206         r_frame++; // used only by R_GetCurrentTexture
7207
7208         R_ResetViewRendering3D();
7209
7210         R_ClearScreen(r_refdef.fogenabled);
7211         if (r_timereport_active)
7212                 R_TimeReport("viewclear");
7213 }
7214
7215 static void R_BlendView(void)
7216 {
7217         unsigned int permutation;
7218         float uservecs[4][4];
7219
7220         switch (vid.renderpath)
7221         {
7222         case RENDERPATH_GL20:
7223         case RENDERPATH_CGGL:
7224                 permutation =
7225                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7226                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7227                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7228                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7229                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7230
7231                 if (r_bloomstate.texture_screen)
7232                 {
7233                         // make sure the buffer is available
7234                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7235
7236                         R_ResetViewRendering2D();
7237                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7238                         R_Mesh_ColorPointer(NULL, 0, 0);
7239
7240                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7241                         {
7242                                 // declare variables
7243                                 float speed;
7244                                 static float avgspeed;
7245
7246                                 speed = VectorLength(cl.movement_velocity);
7247
7248                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7249                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7250
7251                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7252                                 speed = bound(0, speed, 1);
7253                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7254
7255                                 // calculate values into a standard alpha
7256                                 cl.motionbluralpha = 1 - exp(-
7257                                                 (
7258                                                  (r_motionblur.value * speed / 80)
7259                                                  +
7260                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7261                                                 )
7262                                                 /
7263                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7264                                            );
7265
7266                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7267                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7268                                 // apply the blur
7269                                 if (cl.motionbluralpha > 0)
7270                                 {
7271                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7272                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7273                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7274                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7275                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7276                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7277                                 }
7278                         }
7279
7280                         // copy view into the screen texture
7281                         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);
7282                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7283                 }
7284                 else if (!r_bloomstate.texture_bloom)
7285                 {
7286                         // we may still have to do view tint...
7287                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7288                         {
7289                                 // apply a color tint to the whole view
7290                                 R_ResetViewRendering2D();
7291                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7292                                 R_Mesh_ColorPointer(NULL, 0, 0);
7293                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7294                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7295                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7296                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7297                         }
7298                         break; // no screen processing, no bloom, skip it
7299                 }
7300
7301                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7302                 {
7303                         // render simple bloom effect
7304                         // copy the screen and shrink it and darken it for the bloom process
7305                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7306                         // make the bloom texture
7307                         R_Bloom_MakeTexture();
7308                 }
7309
7310 #if _MSC_VER >= 1400
7311 #define sscanf sscanf_s
7312 #endif
7313                 memset(uservecs, 0, sizeof(uservecs));
7314                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7315                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7316                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7317                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7318
7319                 R_ResetViewRendering2D();
7320                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7321                 R_Mesh_ColorPointer(NULL, 0, 0);
7322                 GL_Color(1, 1, 1, 1);
7323                 GL_BlendFunc(GL_ONE, GL_ZERO);
7324                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7325                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7326
7327                 switch(vid.renderpath)
7328                 {
7329                 case RENDERPATH_GL20:
7330                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7331                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7332                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7333                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7334                         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]);
7335                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7336                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7337                         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]);
7338                         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]);
7339                         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]);
7340                         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]);
7341                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7342                         break;
7343                 case RENDERPATH_CGGL:
7344 #ifdef SUPPORTCG
7345                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7346                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7347                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7348                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7349                         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
7350                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7351                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7352                         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
7353                         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
7354                         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
7355                         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
7356                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7357 #endif
7358                         break;
7359                 default:
7360                         break;
7361                 }
7362                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7363                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7364                 break;
7365         case RENDERPATH_GL13:
7366         case RENDERPATH_GL11:
7367                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7368                 {
7369                         // apply a color tint to the whole view
7370                         R_ResetViewRendering2D();
7371                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7372                         R_Mesh_ColorPointer(NULL, 0, 0);
7373                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7374                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7375                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7376                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7377                 }
7378                 break;
7379         }
7380 }
7381
7382 matrix4x4_t r_waterscrollmatrix;
7383
7384 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7385 {
7386         if (r_refdef.fog_density)
7387         {
7388                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7389                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7390                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7391
7392                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7393                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7394                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7395                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7396
7397                 {
7398                         vec3_t fogvec;
7399                         VectorCopy(r_refdef.fogcolor, fogvec);
7400                         //   color.rgb *= ContrastBoost * SceneBrightness;
7401                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7402                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7403                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7404                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7405                 }
7406         }
7407 }
7408
7409 void R_UpdateVariables(void)
7410 {
7411         R_Textures_Frame();
7412
7413         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7414
7415         r_refdef.farclip = r_farclip_base.value;
7416         if (r_refdef.scene.worldmodel)
7417                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7418         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7419
7420         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7421                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7422         r_refdef.polygonfactor = 0;
7423         r_refdef.polygonoffset = 0;
7424         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7425         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7426
7427         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7428         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7429         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7430         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7431         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7432         if (r_showsurfaces.integer)
7433         {
7434                 r_refdef.scene.rtworld = false;
7435                 r_refdef.scene.rtworldshadows = false;
7436                 r_refdef.scene.rtdlight = false;
7437                 r_refdef.scene.rtdlightshadows = false;
7438                 r_refdef.lightmapintensity = 0;
7439         }
7440
7441         if (gamemode == GAME_NEHAHRA)
7442         {
7443                 if (gl_fogenable.integer)
7444                 {
7445                         r_refdef.oldgl_fogenable = true;
7446                         r_refdef.fog_density = gl_fogdensity.value;
7447                         r_refdef.fog_red = gl_fogred.value;
7448                         r_refdef.fog_green = gl_foggreen.value;
7449                         r_refdef.fog_blue = gl_fogblue.value;
7450                         r_refdef.fog_alpha = 1;
7451                         r_refdef.fog_start = 0;
7452                         r_refdef.fog_end = gl_skyclip.value;
7453                         r_refdef.fog_height = 1<<30;
7454                         r_refdef.fog_fadedepth = 128;
7455                 }
7456                 else if (r_refdef.oldgl_fogenable)
7457                 {
7458                         r_refdef.oldgl_fogenable = false;
7459                         r_refdef.fog_density = 0;
7460                         r_refdef.fog_red = 0;
7461                         r_refdef.fog_green = 0;
7462                         r_refdef.fog_blue = 0;
7463                         r_refdef.fog_alpha = 0;
7464                         r_refdef.fog_start = 0;
7465                         r_refdef.fog_end = 0;
7466                         r_refdef.fog_height = 1<<30;
7467                         r_refdef.fog_fadedepth = 128;
7468                 }
7469         }
7470
7471         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7472         r_refdef.fog_start = max(0, r_refdef.fog_start);
7473         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7474
7475         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7476
7477         if (r_refdef.fog_density && r_drawfog.integer)
7478         {
7479                 r_refdef.fogenabled = true;
7480                 // this is the point where the fog reaches 0.9986 alpha, which we
7481                 // consider a good enough cutoff point for the texture
7482                 // (0.9986 * 256 == 255.6)
7483                 if (r_fog_exp2.integer)
7484                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7485                 else
7486                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7487                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7488                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7489                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7490                 // fog color was already set
7491                 // update the fog texture
7492                 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)
7493                         R_BuildFogTexture();
7494         }
7495         else
7496                 r_refdef.fogenabled = false;
7497
7498         switch(vid.renderpath)
7499         {
7500         case RENDERPATH_GL20:
7501         case RENDERPATH_CGGL:
7502                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7503                 {
7504                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7505                         {
7506                                 // build GLSL gamma texture
7507 #define RAMPWIDTH 256
7508                                 unsigned short ramp[RAMPWIDTH * 3];
7509                                 unsigned char rampbgr[RAMPWIDTH][4];
7510                                 int i;
7511
7512                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7513
7514                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7515                                 for(i = 0; i < RAMPWIDTH; ++i)
7516                                 {
7517                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7518                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7519                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7520                                         rampbgr[i][3] = 0;
7521                                 }
7522                                 if (r_texture_gammaramps)
7523                                 {
7524                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7525                                 }
7526                                 else
7527                                 {
7528                                         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);
7529                                 }
7530                         }
7531                 }
7532                 else
7533                 {
7534                         // remove GLSL gamma texture
7535                 }
7536                 break;
7537         case RENDERPATH_GL13:
7538         case RENDERPATH_GL11:
7539                 break;
7540         }
7541 }
7542
7543 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7544 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7545 /*
7546 ================
7547 R_SelectScene
7548 ================
7549 */
7550 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7551         if( scenetype != r_currentscenetype ) {
7552                 // store the old scenetype
7553                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7554                 r_currentscenetype = scenetype;
7555                 // move in the new scene
7556                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7557         }
7558 }
7559
7560 /*
7561 ================
7562 R_GetScenePointer
7563 ================
7564 */
7565 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7566 {
7567         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7568         if( scenetype == r_currentscenetype ) {
7569                 return &r_refdef.scene;
7570         } else {
7571                 return &r_scenes_store[ scenetype ];
7572         }
7573 }
7574
7575 /*
7576 ================
7577 R_RenderView
7578 ================
7579 */
7580 void R_RenderView(void)
7581 {
7582         if (r_timereport_active)
7583                 R_TimeReport("start");
7584         r_frame++; // used only by R_GetCurrentTexture
7585         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7586
7587         if (!r_drawentities.integer)
7588                 r_refdef.scene.numentities = 0;
7589
7590         R_AnimCache_ClearCache();
7591         R_FrameData_NewFrame();
7592
7593         if (r_refdef.view.isoverlay)
7594         {
7595                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7596                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7597                 R_TimeReport("depthclear");
7598
7599                 r_refdef.view.showdebug = false;
7600
7601                 r_waterstate.enabled = false;
7602                 r_waterstate.numwaterplanes = 0;
7603
7604                 R_RenderScene();
7605
7606                 CHECKGLERROR
7607                 return;
7608         }
7609
7610         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7611                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7612
7613         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7614
7615         // break apart the view matrix into vectors for various purposes
7616         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7617         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7618         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7619         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7620         // make an inverted copy of the view matrix for tracking sprites
7621         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7622
7623         R_Shadow_UpdateWorldLightSelection();
7624
7625         R_Bloom_StartFrame();
7626         R_Water_StartFrame();
7627
7628         CHECKGLERROR
7629         if (r_timereport_active)
7630                 R_TimeReport("viewsetup");
7631
7632         R_ResetViewRendering3D();
7633
7634         if (r_refdef.view.clear || r_refdef.fogenabled)
7635         {
7636                 R_ClearScreen(r_refdef.fogenabled);
7637                 if (r_timereport_active)
7638                         R_TimeReport("viewclear");
7639         }
7640         r_refdef.view.clear = true;
7641
7642         // this produces a bloom texture to be used in R_BlendView() later
7643         if (r_hdr.integer && r_bloomstate.bloomwidth)
7644                 R_HDR_RenderBloomTexture();
7645
7646         r_refdef.view.showdebug = true;
7647
7648         R_View_Update();
7649         if (r_timereport_active)
7650                 R_TimeReport("visibility");
7651
7652         r_waterstate.numwaterplanes = 0;
7653         if (r_waterstate.enabled)
7654                 R_RenderWaterPlanes();
7655
7656         R_RenderScene();
7657         r_waterstate.numwaterplanes = 0;
7658
7659         R_BlendView();
7660         if (r_timereport_active)
7661                 R_TimeReport("blendview");
7662
7663         GL_Scissor(0, 0, vid.width, vid.height);
7664         GL_ScissorTest(false);
7665         CHECKGLERROR
7666 }
7667
7668 void R_RenderWaterPlanes(void)
7669 {
7670         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7671         {
7672                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7673                 if (r_timereport_active)
7674                         R_TimeReport("waterworld");
7675         }
7676
7677         // don't let sound skip if going slow
7678         if (r_refdef.scene.extraupdate)
7679                 S_ExtraUpdate ();
7680
7681         R_DrawModelsAddWaterPlanes();
7682         if (r_timereport_active)
7683                 R_TimeReport("watermodels");
7684
7685         if (r_waterstate.numwaterplanes)
7686         {
7687                 R_Water_ProcessPlanes();
7688                 if (r_timereport_active)
7689                         R_TimeReport("waterscenes");
7690         }
7691 }
7692
7693 extern void R_DrawLightningBeams (void);
7694 extern void VM_CL_AddPolygonsToMeshQueue (void);
7695 extern void R_DrawPortals (void);
7696 extern cvar_t cl_locs_show;
7697 static void R_DrawLocs(void);
7698 static void R_DrawEntityBBoxes(void);
7699 static void R_DrawModelDecals(void);
7700 extern cvar_t cl_decals_newsystem;
7701 extern qboolean r_shadow_usingdeferredprepass;
7702 void R_RenderScene(void)
7703 {
7704         r_refdef.stats.renders++;
7705
7706         R_UpdateFogColor();
7707
7708         // don't let sound skip if going slow
7709         if (r_refdef.scene.extraupdate)
7710                 S_ExtraUpdate ();
7711
7712         R_MeshQueue_BeginScene();
7713
7714         R_SkyStartFrame();
7715
7716         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);
7717
7718         if (cl.csqc_vidvars.drawworld)
7719         {
7720                 // don't let sound skip if going slow
7721                 if (r_refdef.scene.extraupdate)
7722                         S_ExtraUpdate ();
7723
7724                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7725                 {
7726                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7727                         if (r_timereport_active)
7728                                 R_TimeReport("worldsky");
7729                 }
7730
7731                 if (R_DrawBrushModelsSky() && r_timereport_active)
7732                         R_TimeReport("bmodelsky");
7733
7734                 if (skyrendermasked && skyrenderlater)
7735                 {
7736                         // we have to force off the water clipping plane while rendering sky
7737                         R_SetupView(false);
7738                         R_Sky();
7739                         R_SetupView(true);
7740                         if (r_timereport_active)
7741                                 R_TimeReport("sky");
7742                 }
7743         }
7744
7745         R_AnimCache_CacheVisibleEntities();
7746         if (r_timereport_active)
7747                 R_TimeReport("animation");
7748
7749         R_Shadow_PrepareLights();
7750         if (r_timereport_active)
7751                 R_TimeReport("preparelights");
7752
7753         if (r_shadow_usingdeferredprepass)
7754                 R_Shadow_DrawPrepass();
7755
7756         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7757         {
7758                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7759                 if (r_timereport_active)
7760                         R_TimeReport("worlddepth");
7761         }
7762         if (r_depthfirst.integer >= 2)
7763         {
7764                 R_DrawModelsDepth();
7765                 if (r_timereport_active)
7766                         R_TimeReport("modeldepth");
7767         }
7768
7769         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7770         {
7771                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7772                 if (r_timereport_active)
7773                         R_TimeReport("world");
7774         }
7775
7776         // don't let sound skip if going slow
7777         if (r_refdef.scene.extraupdate)
7778                 S_ExtraUpdate ();
7779
7780         R_DrawModels();
7781         if (r_timereport_active)
7782                 R_TimeReport("models");
7783
7784         // don't let sound skip if going slow
7785         if (r_refdef.scene.extraupdate)
7786                 S_ExtraUpdate ();
7787
7788         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7789         {
7790                 R_DrawModelShadows();
7791                 R_ResetViewRendering3D();
7792                 // don't let sound skip if going slow
7793                 if (r_refdef.scene.extraupdate)
7794                         S_ExtraUpdate ();
7795         }
7796
7797         if (!r_shadow_usingdeferredprepass)
7798         {
7799                 R_Shadow_DrawLights();
7800                 if (r_timereport_active)
7801                         R_TimeReport("rtlights");
7802         }
7803
7804         // don't let sound skip if going slow
7805         if (r_refdef.scene.extraupdate)
7806                 S_ExtraUpdate ();
7807
7808         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7809         {
7810                 R_DrawModelShadows();
7811                 R_ResetViewRendering3D();
7812                 // don't let sound skip if going slow
7813                 if (r_refdef.scene.extraupdate)
7814                         S_ExtraUpdate ();
7815         }
7816
7817         if (cl.csqc_vidvars.drawworld)
7818         {
7819                 if (cl_decals_newsystem.integer)
7820                 {
7821                         R_DrawModelDecals();
7822                         if (r_timereport_active)
7823                                 R_TimeReport("modeldecals");
7824                 }
7825                 else
7826                 {
7827                         R_DrawDecals();
7828                         if (r_timereport_active)
7829                                 R_TimeReport("decals");
7830                 }
7831
7832                 R_DrawParticles();
7833                 if (r_timereport_active)
7834                         R_TimeReport("particles");
7835
7836                 R_DrawExplosions();
7837                 if (r_timereport_active)
7838                         R_TimeReport("explosions");
7839
7840                 R_DrawLightningBeams();
7841                 if (r_timereport_active)
7842                         R_TimeReport("lightning");
7843         }
7844
7845         VM_CL_AddPolygonsToMeshQueue();
7846
7847         if (r_refdef.view.showdebug)
7848         {
7849                 if (cl_locs_show.integer)
7850                 {
7851                         R_DrawLocs();
7852                         if (r_timereport_active)
7853                                 R_TimeReport("showlocs");
7854                 }
7855
7856                 if (r_drawportals.integer)
7857                 {
7858                         R_DrawPortals();
7859                         if (r_timereport_active)
7860                                 R_TimeReport("portals");
7861                 }
7862
7863                 if (r_showbboxes.value > 0)
7864                 {
7865                         R_DrawEntityBBoxes();
7866                         if (r_timereport_active)
7867                                 R_TimeReport("bboxes");
7868                 }
7869         }
7870
7871         R_MeshQueue_RenderTransparent();
7872         if (r_timereport_active)
7873                 R_TimeReport("drawtrans");
7874
7875         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))
7876         {
7877                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7878                 if (r_timereport_active)
7879                         R_TimeReport("worlddebug");
7880                 R_DrawModelsDebug();
7881                 if (r_timereport_active)
7882                         R_TimeReport("modeldebug");
7883         }
7884
7885         if (cl.csqc_vidvars.drawworld)
7886         {
7887                 R_Shadow_DrawCoronas();
7888                 if (r_timereport_active)
7889                         R_TimeReport("coronas");
7890         }
7891
7892         // don't let sound skip if going slow
7893         if (r_refdef.scene.extraupdate)
7894                 S_ExtraUpdate ();
7895
7896         R_ResetViewRendering2D();
7897 }
7898
7899 static const unsigned short bboxelements[36] =
7900 {
7901         5, 1, 3, 5, 3, 7,
7902         6, 2, 0, 6, 0, 4,
7903         7, 3, 2, 7, 2, 6,
7904         4, 0, 1, 4, 1, 5,
7905         4, 5, 7, 4, 7, 6,
7906         1, 0, 2, 1, 2, 3,
7907 };
7908
7909 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7910 {
7911         int i;
7912         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7913
7914         RSurf_ActiveWorldEntity();
7915
7916         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7917         GL_DepthMask(false);
7918         GL_DepthRange(0, 1);
7919         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7920         R_Mesh_ResetTextureState();
7921
7922         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7923         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7924         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7925         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7926         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7927         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7928         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7929         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7930         R_FillColors(color4f, 8, cr, cg, cb, ca);
7931         if (r_refdef.fogenabled)
7932         {
7933                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7934                 {
7935                         f1 = RSurf_FogVertex(v);
7936                         f2 = 1 - f1;
7937                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7938                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7939                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7940                 }
7941         }
7942         R_Mesh_VertexPointer(vertex3f, 0, 0);
7943         R_Mesh_ColorPointer(color4f, 0, 0);
7944         R_Mesh_ResetTextureState();
7945         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7946         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
7947 }
7948
7949 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7950 {
7951         int i;
7952         float color[4];
7953         prvm_edict_t *edict;
7954         prvm_prog_t *prog_save = prog;
7955
7956         // this function draws bounding boxes of server entities
7957         if (!sv.active)
7958                 return;
7959
7960         GL_CullFace(GL_NONE);
7961         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7962
7963         prog = 0;
7964         SV_VM_Begin();
7965         for (i = 0;i < numsurfaces;i++)
7966         {
7967                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7968                 switch ((int)edict->fields.server->solid)
7969                 {
7970                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7971                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7972                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7973                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7974                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7975                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7976                 }
7977                 color[3] *= r_showbboxes.value;
7978                 color[3] = bound(0, color[3], 1);
7979                 GL_DepthTest(!r_showdisabledepthtest.integer);
7980                 GL_CullFace(r_refdef.view.cullface_front);
7981                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7982         }
7983         SV_VM_End();
7984         prog = prog_save;
7985 }
7986
7987 static void R_DrawEntityBBoxes(void)
7988 {
7989         int i;
7990         prvm_edict_t *edict;
7991         vec3_t center;
7992         prvm_prog_t *prog_save = prog;
7993
7994         // this function draws bounding boxes of server entities
7995         if (!sv.active)
7996                 return;
7997
7998         prog = 0;
7999         SV_VM_Begin();
8000         for (i = 0;i < prog->num_edicts;i++)
8001         {
8002                 edict = PRVM_EDICT_NUM(i);
8003                 if (edict->priv.server->free)
8004                         continue;
8005                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8006                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8007                         continue;
8008                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8009                         continue;
8010                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8011                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8012         }
8013         SV_VM_End();
8014         prog = prog_save;
8015 }
8016
8017 static const int nomodelelement3i[24] =
8018 {
8019         5, 2, 0,
8020         5, 1, 2,
8021         5, 0, 3,
8022         5, 3, 1,
8023         0, 2, 4,
8024         2, 1, 4,
8025         3, 0, 4,
8026         1, 3, 4
8027 };
8028
8029 static const unsigned short nomodelelement3s[24] =
8030 {
8031         5, 2, 0,
8032         5, 1, 2,
8033         5, 0, 3,
8034         5, 3, 1,
8035         0, 2, 4,
8036         2, 1, 4,
8037         3, 0, 4,
8038         1, 3, 4
8039 };
8040
8041 static const float nomodelvertex3f[6*3] =
8042 {
8043         -16,   0,   0,
8044          16,   0,   0,
8045           0, -16,   0,
8046           0,  16,   0,
8047           0,   0, -16,
8048           0,   0,  16
8049 };
8050
8051 static const float nomodelcolor4f[6*4] =
8052 {
8053         0.0f, 0.0f, 0.5f, 1.0f,
8054         0.0f, 0.0f, 0.5f, 1.0f,
8055         0.0f, 0.5f, 0.0f, 1.0f,
8056         0.0f, 0.5f, 0.0f, 1.0f,
8057         0.5f, 0.0f, 0.0f, 1.0f,
8058         0.5f, 0.0f, 0.0f, 1.0f
8059 };
8060
8061 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8062 {
8063         int i;
8064         float f1, f2, *c;
8065         float color4f[6*4];
8066
8067         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);
8068
8069         // this is only called once per entity so numsurfaces is always 1, and
8070         // surfacelist is always {0}, so this code does not handle batches
8071
8072         if (rsurface.ent_flags & RENDER_ADDITIVE)
8073         {
8074                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8075                 GL_DepthMask(false);
8076         }
8077         else if (rsurface.colormod[3] < 1)
8078         {
8079                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8080                 GL_DepthMask(false);
8081         }
8082         else
8083         {
8084                 GL_BlendFunc(GL_ONE, GL_ZERO);
8085                 GL_DepthMask(true);
8086         }
8087         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8088         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8089         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8090         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8091         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8092         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8093         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8094         R_Mesh_ColorPointer(color4f, 0, 0);
8095         for (i = 0, c = color4f;i < 6;i++, c += 4)
8096         {
8097                 c[0] *= rsurface.colormod[0];
8098                 c[1] *= rsurface.colormod[1];
8099                 c[2] *= rsurface.colormod[2];
8100                 c[3] *= rsurface.colormod[3];
8101         }
8102         if (r_refdef.fogenabled)
8103         {
8104                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8105                 {
8106                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8107                         f2 = 1 - f1;
8108                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8109                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8110                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8111                 }
8112         }
8113         R_Mesh_ResetTextureState();
8114         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8115 }
8116
8117 void R_DrawNoModel(entity_render_t *ent)
8118 {
8119         vec3_t org;
8120         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8121         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8122                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8123         else
8124                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8125 }
8126
8127 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8128 {
8129         vec3_t right1, right2, diff, normal;
8130
8131         VectorSubtract (org2, org1, normal);
8132
8133         // calculate 'right' vector for start
8134         VectorSubtract (r_refdef.view.origin, org1, diff);
8135         CrossProduct (normal, diff, right1);
8136         VectorNormalize (right1);
8137
8138         // calculate 'right' vector for end
8139         VectorSubtract (r_refdef.view.origin, org2, diff);
8140         CrossProduct (normal, diff, right2);
8141         VectorNormalize (right2);
8142
8143         vert[ 0] = org1[0] + width * right1[0];
8144         vert[ 1] = org1[1] + width * right1[1];
8145         vert[ 2] = org1[2] + width * right1[2];
8146         vert[ 3] = org1[0] - width * right1[0];
8147         vert[ 4] = org1[1] - width * right1[1];
8148         vert[ 5] = org1[2] - width * right1[2];
8149         vert[ 6] = org2[0] - width * right2[0];
8150         vert[ 7] = org2[1] - width * right2[1];
8151         vert[ 8] = org2[2] - width * right2[2];
8152         vert[ 9] = org2[0] + width * right2[0];
8153         vert[10] = org2[1] + width * right2[1];
8154         vert[11] = org2[2] + width * right2[2];
8155 }
8156
8157 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)
8158 {
8159         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8160         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8161         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8162         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8163         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8164         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8165         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8166         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8167         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8168         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8169         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8170         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8171 }
8172
8173 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8174 {
8175         int i;
8176         float *vertex3f;
8177         float v[3];
8178         VectorSet(v, x, y, z);
8179         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8180                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8181                         break;
8182         if (i == mesh->numvertices)
8183         {
8184                 if (mesh->numvertices < mesh->maxvertices)
8185                 {
8186                         VectorCopy(v, vertex3f);
8187                         mesh->numvertices++;
8188                 }
8189                 return mesh->numvertices;
8190         }
8191         else
8192                 return i;
8193 }
8194
8195 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8196 {
8197         int i;
8198         int *e, element[3];
8199         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8200         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8201         e = mesh->element3i + mesh->numtriangles * 3;
8202         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8203         {
8204                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8205                 if (mesh->numtriangles < mesh->maxtriangles)
8206                 {
8207                         *e++ = element[0];
8208                         *e++ = element[1];
8209                         *e++ = element[2];
8210                         mesh->numtriangles++;
8211                 }
8212                 element[1] = element[2];
8213         }
8214 }
8215
8216 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8217 {
8218         int i;
8219         int *e, element[3];
8220         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8221         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8222         e = mesh->element3i + mesh->numtriangles * 3;
8223         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8224         {
8225                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8226                 if (mesh->numtriangles < mesh->maxtriangles)
8227                 {
8228                         *e++ = element[0];
8229                         *e++ = element[1];
8230                         *e++ = element[2];
8231                         mesh->numtriangles++;
8232                 }
8233                 element[1] = element[2];
8234         }
8235 }
8236
8237 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8238 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8239 {
8240         int planenum, planenum2;
8241         int w;
8242         int tempnumpoints;
8243         mplane_t *plane, *plane2;
8244         double maxdist;
8245         double temppoints[2][256*3];
8246         // figure out how large a bounding box we need to properly compute this brush
8247         maxdist = 0;
8248         for (w = 0;w < numplanes;w++)
8249                 maxdist = max(maxdist, fabs(planes[w].dist));
8250         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8251         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8252         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8253         {
8254                 w = 0;
8255                 tempnumpoints = 4;
8256                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8257                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8258                 {
8259                         if (planenum2 == planenum)
8260                                 continue;
8261                         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);
8262                         w = !w;
8263                 }
8264                 if (tempnumpoints < 3)
8265                         continue;
8266                 // generate elements forming a triangle fan for this polygon
8267                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8268         }
8269 }
8270
8271 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)
8272 {
8273         texturelayer_t *layer;
8274         layer = t->currentlayers + t->currentnumlayers++;
8275         layer->type = type;
8276         layer->depthmask = depthmask;
8277         layer->blendfunc1 = blendfunc1;
8278         layer->blendfunc2 = blendfunc2;
8279         layer->texture = texture;
8280         layer->texmatrix = *matrix;
8281         layer->color[0] = r;
8282         layer->color[1] = g;
8283         layer->color[2] = b;
8284         layer->color[3] = a;
8285 }
8286
8287 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8288 {
8289         double index, f;
8290         index = parms[2] + r_refdef.scene.time * parms[3];
8291         index -= floor(index);
8292         switch (func)
8293         {
8294         default:
8295         case Q3WAVEFUNC_NONE:
8296         case Q3WAVEFUNC_NOISE:
8297         case Q3WAVEFUNC_COUNT:
8298                 f = 0;
8299                 break;
8300         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8301         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8302         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8303         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8304         case Q3WAVEFUNC_TRIANGLE:
8305                 index *= 4;
8306                 f = index - floor(index);
8307                 if (index < 1)
8308                         f = f;
8309                 else if (index < 2)
8310                         f = 1 - f;
8311                 else if (index < 3)
8312                         f = -f;
8313                 else
8314                         f = -(1 - f);
8315                 break;
8316         }
8317         return (float)(parms[0] + parms[1] * f);
8318 }
8319
8320 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8321 {
8322         int w, h, idx;
8323         float f;
8324         float tcmat[12];
8325         matrix4x4_t matrix, temp;
8326         switch(tcmod->tcmod)
8327         {
8328                 case Q3TCMOD_COUNT:
8329                 case Q3TCMOD_NONE:
8330                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8331                                 matrix = r_waterscrollmatrix;
8332                         else
8333                                 matrix = identitymatrix;
8334                         break;
8335                 case Q3TCMOD_ENTITYTRANSLATE:
8336                         // this is used in Q3 to allow the gamecode to control texcoord
8337                         // scrolling on the entity, which is not supported in darkplaces yet.
8338                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8339                         break;
8340                 case Q3TCMOD_ROTATE:
8341                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8342                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8343                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8344                         break;
8345                 case Q3TCMOD_SCALE:
8346                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8347                         break;
8348                 case Q3TCMOD_SCROLL:
8349                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8350                         break;
8351                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8352                         w = (int) tcmod->parms[0];
8353                         h = (int) tcmod->parms[1];
8354                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8355                         f = f - floor(f);
8356                         idx = (int) floor(f * w * h);
8357                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8358                         break;
8359                 case Q3TCMOD_STRETCH:
8360                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8361                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8362                         break;
8363                 case Q3TCMOD_TRANSFORM:
8364                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8365                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8366                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8367                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8368                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8369                         break;
8370                 case Q3TCMOD_TURBULENT:
8371                         // this is handled in the RSurf_PrepareVertices function
8372                         matrix = identitymatrix;
8373                         break;
8374         }
8375         temp = *texmatrix;
8376         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8377 }
8378
8379 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8380 {
8381         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8382         char name[MAX_QPATH];
8383         skinframe_t *skinframe;
8384         unsigned char pixels[296*194];
8385         strlcpy(cache->name, skinname, sizeof(cache->name));
8386         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8387         if (developer_loading.integer)
8388                 Con_Printf("loading %s\n", name);
8389         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8390         if (!skinframe || !skinframe->base)
8391         {
8392                 unsigned char *f;
8393                 fs_offset_t filesize;
8394                 skinframe = NULL;
8395                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8396                 if (f)
8397                 {
8398                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8399                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8400                         Mem_Free(f);
8401                 }
8402         }
8403         cache->skinframe = skinframe;
8404 }
8405
8406 texture_t *R_GetCurrentTexture(texture_t *t)
8407 {
8408         int i;
8409         const entity_render_t *ent = rsurface.entity;
8410         dp_model_t *model = ent->model;
8411         q3shaderinfo_layer_tcmod_t *tcmod;
8412
8413         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
8414                 return t->currentframe;
8415         t->update_lastrenderframe = r_frame;
8416         t->update_lastrenderentity = (void *)ent;
8417
8418         // switch to an alternate material if this is a q1bsp animated material
8419         {
8420                 texture_t *texture = t;
8421                 int s = rsurface.ent_skinnum;
8422                 if ((unsigned int)s >= (unsigned int)model->numskins)
8423                         s = 0;
8424                 if (model->skinscenes)
8425                 {
8426                         if (model->skinscenes[s].framecount > 1)
8427                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8428                         else
8429                                 s = model->skinscenes[s].firstframe;
8430                 }
8431                 if (s > 0)
8432                         t = t + s * model->num_surfaces;
8433                 if (t->animated)
8434                 {
8435                         // use an alternate animation if the entity's frame is not 0,
8436                         // and only if the texture has an alternate animation
8437                         if (rsurface.ent_alttextures && t->anim_total[1])
8438                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8439                         else
8440                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8441                 }
8442                 texture->currentframe = t;
8443         }
8444
8445         // update currentskinframe to be a qw skin or animation frame
8446         if (rsurface.ent_qwskin >= 0)
8447         {
8448                 i = rsurface.ent_qwskin;
8449                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8450                 {
8451                         r_qwskincache_size = cl.maxclients;
8452                         if (r_qwskincache)
8453                                 Mem_Free(r_qwskincache);
8454                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8455                 }
8456                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8457                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8458                 t->currentskinframe = r_qwskincache[i].skinframe;
8459                 if (t->currentskinframe == NULL)
8460                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8461         }
8462         else if (t->numskinframes >= 2)
8463                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8464         if (t->backgroundnumskinframes >= 2)
8465                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8466
8467         t->currentmaterialflags = t->basematerialflags;
8468         t->currentalpha = rsurface.colormod[3];
8469         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8470                 t->currentalpha *= r_wateralpha.value;
8471         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8472                 t->currentalpha *= t->r_water_wateralpha;
8473         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8474                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8475         if (!(rsurface.ent_flags & RENDER_LIGHT))
8476                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8477         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8478         {
8479                 // pick a model lighting mode
8480                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8481                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8482                 else
8483                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8484         }
8485         if (rsurface.ent_flags & RENDER_ADDITIVE)
8486                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8487         else if (t->currentalpha < 1)
8488                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8489         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8490                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8491         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8492                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8493         if (t->backgroundnumskinframes)
8494                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8495         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8496         {
8497                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8498                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8499         }
8500         else
8501                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8502         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8503                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8504
8505         // there is no tcmod
8506         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8507         {
8508                 t->currenttexmatrix = r_waterscrollmatrix;
8509                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8510         }
8511         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8512         {
8513                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8514                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8515         }
8516
8517         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8518                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8519         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8520                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8521
8522         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8523         if (t->currentskinframe->qpixels)
8524                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8525         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8526         if (!t->basetexture)
8527                 t->basetexture = r_texture_notexture;
8528         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8529         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8530         t->nmaptexture = t->currentskinframe->nmap;
8531         if (!t->nmaptexture)
8532                 t->nmaptexture = r_texture_blanknormalmap;
8533         t->glosstexture = r_texture_black;
8534         t->glowtexture = t->currentskinframe->glow;
8535         t->fogtexture = t->currentskinframe->fog;
8536         if (t->backgroundnumskinframes)
8537         {
8538                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8539                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8540                 t->backgroundglosstexture = r_texture_black;
8541                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8542                 if (!t->backgroundnmaptexture)
8543                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8544         }
8545         else
8546         {
8547                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8548                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8549                 t->backgroundglosstexture = r_texture_black;
8550                 t->backgroundglowtexture = NULL;
8551         }
8552         t->specularpower = r_shadow_glossexponent.value;
8553         // TODO: store reference values for these in the texture?
8554         t->specularscale = 0;
8555         if (r_shadow_gloss.integer > 0)
8556         {
8557                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8558                 {
8559                         if (r_shadow_glossintensity.value > 0)
8560                         {
8561                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8562                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8563                                 t->specularscale = r_shadow_glossintensity.value;
8564                         }
8565                 }
8566                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8567                 {
8568                         t->glosstexture = r_texture_white;
8569                         t->backgroundglosstexture = r_texture_white;
8570                         t->specularscale = r_shadow_gloss2intensity.value;
8571                         t->specularpower = r_shadow_gloss2exponent.value;
8572                 }
8573         }
8574         t->specularscale *= t->specularscalemod;
8575         t->specularpower *= t->specularpowermod;
8576
8577         // lightmaps mode looks bad with dlights using actual texturing, so turn
8578         // off the colormap and glossmap, but leave the normalmap on as it still
8579         // accurately represents the shading involved
8580         if (gl_lightmaps.integer)
8581         {
8582                 t->basetexture = r_texture_grey128;
8583                 t->pantstexture = r_texture_black;
8584                 t->shirttexture = r_texture_black;
8585                 t->nmaptexture = r_texture_blanknormalmap;
8586                 t->glosstexture = r_texture_black;
8587                 t->glowtexture = NULL;
8588                 t->fogtexture = NULL;
8589                 t->backgroundbasetexture = NULL;
8590                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8591                 t->backgroundglosstexture = r_texture_black;
8592                 t->backgroundglowtexture = NULL;
8593                 t->specularscale = 0;
8594                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8595         }
8596
8597         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8598         VectorClear(t->dlightcolor);
8599         t->currentnumlayers = 0;
8600         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8601         {
8602                 int blendfunc1, blendfunc2;
8603                 qboolean depthmask;
8604                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8605                 {
8606                         blendfunc1 = GL_SRC_ALPHA;
8607                         blendfunc2 = GL_ONE;
8608                 }
8609                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8610                 {
8611                         blendfunc1 = GL_SRC_ALPHA;
8612                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8613                 }
8614                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8615                 {
8616                         blendfunc1 = t->customblendfunc[0];
8617                         blendfunc2 = t->customblendfunc[1];
8618                 }
8619                 else
8620                 {
8621                         blendfunc1 = GL_ONE;
8622                         blendfunc2 = GL_ZERO;
8623                 }
8624                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8625                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8626                 {
8627                         // fullbright is not affected by r_refdef.lightmapintensity
8628                         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]);
8629                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8630                                 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]);
8631                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8632                                 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]);
8633                 }
8634                 else
8635                 {
8636                         vec3_t ambientcolor;
8637                         float colorscale;
8638                         // set the color tint used for lights affecting this surface
8639                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8640                         colorscale = 2;
8641                         // q3bsp has no lightmap updates, so the lightstylevalue that
8642                         // would normally be baked into the lightmap must be
8643                         // applied to the color
8644                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8645                         if (model->type == mod_brushq3)
8646                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8647                         colorscale *= r_refdef.lightmapintensity;
8648                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8649                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8650                         // basic lit geometry
8651                         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]);
8652                         // add pants/shirt if needed
8653                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8654                                 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]);
8655                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8656                                 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]);
8657                         // now add ambient passes if needed
8658                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8659                         {
8660                                 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]);
8661                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8662                                         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]);
8663                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8664                                         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]);
8665                         }
8666                 }
8667                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8668                         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]);
8669                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8670                 {
8671                         // if this is opaque use alpha blend which will darken the earlier
8672                         // passes cheaply.
8673                         //
8674                         // if this is an alpha blended material, all the earlier passes
8675                         // were darkened by fog already, so we only need to add the fog
8676                         // color ontop through the fog mask texture
8677                         //
8678                         // if this is an additive blended material, all the earlier passes
8679                         // were darkened by fog already, and we should not add fog color
8680                         // (because the background was not darkened, there is no fog color
8681                         // that was lost behind it).
8682                         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]);
8683                 }
8684         }
8685
8686         return t->currentframe;
8687 }
8688
8689 rsurfacestate_t rsurface;
8690
8691 void R_Mesh_ResizeArrays(int newvertices)
8692 {
8693         float *base;
8694         if (rsurface.array_size >= newvertices)
8695                 return;
8696         if (rsurface.array_modelvertex3f)
8697                 Mem_Free(rsurface.array_modelvertex3f);
8698         rsurface.array_size = (newvertices + 1023) & ~1023;
8699         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8700         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8701         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8702         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8703         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8704         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8705         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8706         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8707         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8708         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8709         rsurface.array_color4f           = base + rsurface.array_size * 27;
8710         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8711 }
8712
8713 void RSurf_ActiveWorldEntity(void)
8714 {
8715         dp_model_t *model = r_refdef.scene.worldmodel;
8716         //if (rsurface.entity == r_refdef.scene.worldentity)
8717         //      return;
8718         rsurface.entity = r_refdef.scene.worldentity;
8719         rsurface.skeleton = NULL;
8720         rsurface.ent_skinnum = 0;
8721         rsurface.ent_qwskin = -1;
8722         rsurface.ent_shadertime = 0;
8723         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8724         if (rsurface.array_size < model->surfmesh.num_vertices)
8725                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8726         rsurface.matrix = identitymatrix;
8727         rsurface.inversematrix = identitymatrix;
8728         rsurface.matrixscale = 1;
8729         rsurface.inversematrixscale = 1;
8730         R_EntityMatrix(&identitymatrix);
8731         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8732         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8733         rsurface.fograngerecip = r_refdef.fograngerecip;
8734         rsurface.fogheightfade = r_refdef.fogheightfade;
8735         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8736         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8737         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8738         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8739         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8740         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8741         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8742         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8743         rsurface.colormod[3] = 1;
8744         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);
8745         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8746         rsurface.frameblend[0].lerp = 1;
8747         rsurface.ent_alttextures = false;
8748         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8749         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8750         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8751         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8752         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8753         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8754         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8755         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8756         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8757         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8758         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8759         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8760         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8761         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8762         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8763         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8764         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8765         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8766         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8767         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8768         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8769         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8770         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8771         rsurface.modelelement3i = model->surfmesh.data_element3i;
8772         rsurface.modelelement3s = model->surfmesh.data_element3s;
8773         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8774         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8775         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8776         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8777         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8778         rsurface.modelsurfaces = model->data_surfaces;
8779         rsurface.generatedvertex = false;
8780         rsurface.vertex3f  = rsurface.modelvertex3f;
8781         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8782         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8783         rsurface.svector3f = rsurface.modelsvector3f;
8784         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8785         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8786         rsurface.tvector3f = rsurface.modeltvector3f;
8787         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8788         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8789         rsurface.normal3f  = rsurface.modelnormal3f;
8790         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8791         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8792         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8793 }
8794
8795 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8796 {
8797         dp_model_t *model = ent->model;
8798         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8799         //      return;
8800         rsurface.entity = (entity_render_t *)ent;
8801         rsurface.skeleton = ent->skeleton;
8802         rsurface.ent_skinnum = ent->skinnum;
8803         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;
8804         rsurface.ent_shadertime = ent->shadertime;
8805         rsurface.ent_flags = ent->flags;
8806         if (rsurface.array_size < model->surfmesh.num_vertices)
8807                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8808         rsurface.matrix = ent->matrix;
8809         rsurface.inversematrix = ent->inversematrix;
8810         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8811         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8812         R_EntityMatrix(&rsurface.matrix);
8813         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8814         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8815         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8816         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8817         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8818         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8819         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8820         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8821         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8822         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8823         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8824         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8825         rsurface.colormod[3] = ent->alpha;
8826         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8827         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8828         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8829         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8830         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8831         if (ent->model->brush.submodel && !prepass)
8832         {
8833                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8834                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8835         }
8836         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8837         {
8838                 if (ent->animcache_vertex3f && !r_framedata_failed)
8839                 {
8840                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8841                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8842                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8843                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8844                 }
8845                 else if (wanttangents)
8846                 {
8847                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8848                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
8849                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
8850                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8851                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
8852                 }
8853                 else if (wantnormals)
8854                 {
8855                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8856                         rsurface.modelsvector3f = NULL;
8857                         rsurface.modeltvector3f = NULL;
8858                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8859                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
8860                 }
8861                 else
8862                 {
8863                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8864                         rsurface.modelsvector3f = NULL;
8865                         rsurface.modeltvector3f = NULL;
8866                         rsurface.modelnormal3f = NULL;
8867                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
8868                 }
8869                 rsurface.modelvertex3f_bufferobject = 0;
8870                 rsurface.modelvertex3f_bufferoffset = 0;
8871                 rsurface.modelsvector3f_bufferobject = 0;
8872                 rsurface.modelsvector3f_bufferoffset = 0;
8873                 rsurface.modeltvector3f_bufferobject = 0;
8874                 rsurface.modeltvector3f_bufferoffset = 0;
8875                 rsurface.modelnormal3f_bufferobject = 0;
8876                 rsurface.modelnormal3f_bufferoffset = 0;
8877                 rsurface.generatedvertex = true;
8878         }
8879         else
8880         {
8881                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8882                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8883                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8884                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8885                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8886                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8887                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8888                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8889                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8890                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8891                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8892                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8893                 rsurface.generatedvertex = false;
8894         }
8895         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8896         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8897         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8898         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8899         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8900         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8901         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8902         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8903         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8904         rsurface.modelelement3i = model->surfmesh.data_element3i;
8905         rsurface.modelelement3s = model->surfmesh.data_element3s;
8906         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8907         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8908         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8909         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8910         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8911         rsurface.modelsurfaces = model->data_surfaces;
8912         rsurface.vertex3f  = rsurface.modelvertex3f;
8913         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8914         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8915         rsurface.svector3f = rsurface.modelsvector3f;
8916         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8917         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8918         rsurface.tvector3f = rsurface.modeltvector3f;
8919         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8920         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8921         rsurface.normal3f  = rsurface.modelnormal3f;
8922         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8923         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8924         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8925 }
8926
8927 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)
8928 {
8929         rsurface.entity = r_refdef.scene.worldentity;
8930         rsurface.skeleton = NULL;
8931         rsurface.ent_skinnum = 0;
8932         rsurface.ent_qwskin = -1;
8933         rsurface.ent_shadertime = shadertime;
8934         rsurface.ent_flags = entflags;
8935         rsurface.modelnum_vertices = numvertices;
8936         rsurface.modelnum_triangles = numtriangles;
8937         if (rsurface.array_size < rsurface.modelnum_vertices)
8938                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
8939         rsurface.matrix = *matrix;
8940         rsurface.inversematrix = *inversematrix;
8941         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8942         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8943         R_EntityMatrix(&rsurface.matrix);
8944         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8945         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8946         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8947         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8948         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8949         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8950         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8951         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8952         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8953         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8954         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8955         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8956         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);
8957         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8958         rsurface.frameblend[0].lerp = 1;
8959         rsurface.ent_alttextures = false;
8960         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8961         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8962         if (wanttangents)
8963         {
8964                 rsurface.modelvertex3f = vertex3f;
8965                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
8966                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
8967                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8968         }
8969         else if (wantnormals)
8970         {
8971                 rsurface.modelvertex3f = vertex3f;
8972                 rsurface.modelsvector3f = NULL;
8973                 rsurface.modeltvector3f = NULL;
8974                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8975         }
8976         else
8977         {
8978                 rsurface.modelvertex3f = vertex3f;
8979                 rsurface.modelsvector3f = NULL;
8980                 rsurface.modeltvector3f = NULL;
8981                 rsurface.modelnormal3f = NULL;
8982         }
8983         rsurface.modelvertex3f_bufferobject = 0;
8984         rsurface.modelvertex3f_bufferoffset = 0;
8985         rsurface.modelsvector3f_bufferobject = 0;
8986         rsurface.modelsvector3f_bufferoffset = 0;
8987         rsurface.modeltvector3f_bufferobject = 0;
8988         rsurface.modeltvector3f_bufferoffset = 0;
8989         rsurface.modelnormal3f_bufferobject = 0;
8990         rsurface.modelnormal3f_bufferoffset = 0;
8991         rsurface.generatedvertex = true;
8992         rsurface.modellightmapcolor4f  = color4f;
8993         rsurface.modellightmapcolor4f_bufferobject = 0;
8994         rsurface.modellightmapcolor4f_bufferoffset = 0;
8995         rsurface.modeltexcoordtexture2f  = texcoord2f;
8996         rsurface.modeltexcoordtexture2f_bufferobject = 0;
8997         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8998         rsurface.modeltexcoordlightmap2f  = NULL;
8999         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9000         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9001         rsurface.modelelement3i = element3i;
9002         rsurface.modelelement3s = element3s;
9003         rsurface.modelelement3i_bufferobject = 0;
9004         rsurface.modelelement3s_bufferobject = 0;
9005         rsurface.modellightmapoffsets = NULL;
9006         rsurface.modelsurfaces = NULL;
9007         rsurface.vertex3f  = rsurface.modelvertex3f;
9008         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9009         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9010         rsurface.svector3f = rsurface.modelsvector3f;
9011         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9012         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9013         rsurface.tvector3f = rsurface.modeltvector3f;
9014         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9015         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9016         rsurface.normal3f  = rsurface.modelnormal3f;
9017         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9018         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9019         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9020
9021         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9022         {
9023                 if ((wantnormals || wanttangents) && !normal3f)
9024                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9025                 if (wanttangents && !svector3f)
9026                         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);
9027         }
9028 }
9029
9030 float RSurf_FogPoint(const float *v)
9031 {
9032         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9033         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9034         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9035         float FogHeightFade = r_refdef.fogheightfade;
9036         float fogfrac;
9037         unsigned int fogmasktableindex;
9038         if (r_refdef.fogplaneviewabove)
9039                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9040         else
9041                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9042         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9043         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9044 }
9045
9046 float RSurf_FogVertex(const float *v)
9047 {
9048         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9049         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9050         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9051         float FogHeightFade = rsurface.fogheightfade;
9052         float fogfrac;
9053         unsigned int fogmasktableindex;
9054         if (r_refdef.fogplaneviewabove)
9055                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9056         else
9057                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9058         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9059         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9060 }
9061
9062 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9063 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9064 {
9065         int deformindex;
9066         int texturesurfaceindex;
9067         int i, j;
9068         float amplitude;
9069         float animpos;
9070         float scale;
9071         const float *v1, *in_tc;
9072         float *out_tc;
9073         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9074         float waveparms[4];
9075         q3shaderinfo_deform_t *deform;
9076         // 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
9077         if (rsurface.generatedvertex)
9078         {
9079                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9080                         generatenormals = true;
9081                 for (i = 0;i < Q3MAXDEFORMS;i++)
9082                 {
9083                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9084                         {
9085                                 generatetangents = true;
9086                                 generatenormals = true;
9087                         }
9088                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9089                                 generatenormals = true;
9090                 }
9091                 if (generatenormals && !rsurface.modelnormal3f)
9092                 {
9093                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9094                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9095                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9096                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9097                 }
9098                 if (generatetangents && !rsurface.modelsvector3f)
9099                 {
9100                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9101                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9102                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9103                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9104                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9105                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9106                         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);
9107                 }
9108         }
9109         rsurface.vertex3f  = rsurface.modelvertex3f;
9110         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9111         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9112         rsurface.svector3f = rsurface.modelsvector3f;
9113         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9114         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9115         rsurface.tvector3f = rsurface.modeltvector3f;
9116         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9117         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9118         rsurface.normal3f  = rsurface.modelnormal3f;
9119         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9120         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9121         // if vertices are deformed (sprite flares and things in maps, possibly
9122         // water waves, bulges and other deformations), generate them into
9123         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9124         // (may be static model data or generated data for an animated model, or
9125         //  the previous deform pass)
9126         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9127         {
9128                 switch (deform->deform)
9129                 {
9130                 default:
9131                 case Q3DEFORM_PROJECTIONSHADOW:
9132                 case Q3DEFORM_TEXT0:
9133                 case Q3DEFORM_TEXT1:
9134                 case Q3DEFORM_TEXT2:
9135                 case Q3DEFORM_TEXT3:
9136                 case Q3DEFORM_TEXT4:
9137                 case Q3DEFORM_TEXT5:
9138                 case Q3DEFORM_TEXT6:
9139                 case Q3DEFORM_TEXT7:
9140                 case Q3DEFORM_NONE:
9141                         break;
9142                 case Q3DEFORM_AUTOSPRITE:
9143                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9144                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9145                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9146                         VectorNormalize(newforward);
9147                         VectorNormalize(newright);
9148                         VectorNormalize(newup);
9149                         // make deformed versions of only the model vertices used by the specified surfaces
9150                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9151                         {
9152                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9153                                 // a single autosprite surface can contain multiple sprites...
9154                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9155                                 {
9156                                         VectorClear(center);
9157                                         for (i = 0;i < 4;i++)
9158                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9159                                         VectorScale(center, 0.25f, center);
9160                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9161                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9162                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9163                                         for (i = 0;i < 4;i++)
9164                                         {
9165                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9166                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9167                                         }
9168                                 }
9169                                 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);
9170                                 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);
9171                         }
9172                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9173                         rsurface.vertex3f_bufferobject = 0;
9174                         rsurface.vertex3f_bufferoffset = 0;
9175                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9176                         rsurface.svector3f_bufferobject = 0;
9177                         rsurface.svector3f_bufferoffset = 0;
9178                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9179                         rsurface.tvector3f_bufferobject = 0;
9180                         rsurface.tvector3f_bufferoffset = 0;
9181                         rsurface.normal3f = rsurface.array_deformednormal3f;
9182                         rsurface.normal3f_bufferobject = 0;
9183                         rsurface.normal3f_bufferoffset = 0;
9184                         break;
9185                 case Q3DEFORM_AUTOSPRITE2:
9186                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9187                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9188                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9189                         VectorNormalize(newforward);
9190                         VectorNormalize(newright);
9191                         VectorNormalize(newup);
9192                         // make deformed versions of only the model vertices used by the specified surfaces
9193                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9194                         {
9195                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9196                                 const float *v1, *v2;
9197                                 vec3_t start, end;
9198                                 float f, l;
9199                                 struct
9200                                 {
9201                                         float length2;
9202                                         const float *v1;
9203                                         const float *v2;
9204                                 }
9205                                 shortest[2];
9206                                 memset(shortest, 0, sizeof(shortest));
9207                                 // a single autosprite surface can contain multiple sprites...
9208                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9209                                 {
9210                                         VectorClear(center);
9211                                         for (i = 0;i < 4;i++)
9212                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9213                                         VectorScale(center, 0.25f, center);
9214                                         // find the two shortest edges, then use them to define the
9215                                         // axis vectors for rotating around the central axis
9216                                         for (i = 0;i < 6;i++)
9217                                         {
9218                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9219                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9220 #if 0
9221                                                 Debug_PolygonBegin(NULL, 0);
9222                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9223                                                 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);
9224                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9225                                                 Debug_PolygonEnd();
9226 #endif
9227                                                 l = VectorDistance2(v1, v2);
9228                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9229                                                 if (v1[2] != v2[2])
9230                                                         l += (1.0f / 1024.0f);
9231                                                 if (shortest[0].length2 > l || i == 0)
9232                                                 {
9233                                                         shortest[1] = shortest[0];
9234                                                         shortest[0].length2 = l;
9235                                                         shortest[0].v1 = v1;
9236                                                         shortest[0].v2 = v2;
9237                                                 }
9238                                                 else if (shortest[1].length2 > l || i == 1)
9239                                                 {
9240                                                         shortest[1].length2 = l;
9241                                                         shortest[1].v1 = v1;
9242                                                         shortest[1].v2 = v2;
9243                                                 }
9244                                         }
9245                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9246                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9247 #if 0
9248                                         Debug_PolygonBegin(NULL, 0);
9249                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9250                                         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);
9251                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9252                                         Debug_PolygonEnd();
9253 #endif
9254                                         // this calculates the right vector from the shortest edge
9255                                         // and the up vector from the edge midpoints
9256                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9257                                         VectorNormalize(right);
9258                                         VectorSubtract(end, start, up);
9259                                         VectorNormalize(up);
9260                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9261                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9262                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9263                                         VectorNegate(forward, forward);
9264                                         VectorReflect(forward, 0, up, forward);
9265                                         VectorNormalize(forward);
9266                                         CrossProduct(up, forward, newright);
9267                                         VectorNormalize(newright);
9268 #if 0
9269                                         Debug_PolygonBegin(NULL, 0);
9270                                         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);
9271                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9272                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9273                                         Debug_PolygonEnd();
9274 #endif
9275 #if 0
9276                                         Debug_PolygonBegin(NULL, 0);
9277                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9278                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9279                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9280                                         Debug_PolygonEnd();
9281 #endif
9282                                         // rotate the quad around the up axis vector, this is made
9283                                         // especially easy by the fact we know the quad is flat,
9284                                         // so we only have to subtract the center position and
9285                                         // measure distance along the right vector, and then
9286                                         // multiply that by the newright vector and add back the
9287                                         // center position
9288                                         // we also need to subtract the old position to undo the
9289                                         // displacement from the center, which we do with a
9290                                         // DotProduct, the subtraction/addition of center is also
9291                                         // optimized into DotProducts here
9292                                         l = DotProduct(right, center);
9293                                         for (i = 0;i < 4;i++)
9294                                         {
9295                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9296                                                 f = DotProduct(right, v1) - l;
9297                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9298                                         }
9299                                 }
9300                                 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);
9301                                 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);
9302                         }
9303                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9304                         rsurface.vertex3f_bufferobject = 0;
9305                         rsurface.vertex3f_bufferoffset = 0;
9306                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9307                         rsurface.svector3f_bufferobject = 0;
9308                         rsurface.svector3f_bufferoffset = 0;
9309                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9310                         rsurface.tvector3f_bufferobject = 0;
9311                         rsurface.tvector3f_bufferoffset = 0;
9312                         rsurface.normal3f = rsurface.array_deformednormal3f;
9313                         rsurface.normal3f_bufferobject = 0;
9314                         rsurface.normal3f_bufferoffset = 0;
9315                         break;
9316                 case Q3DEFORM_NORMAL:
9317                         // deform the normals to make reflections wavey
9318                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9319                         {
9320                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9321                                 for (j = 0;j < surface->num_vertices;j++)
9322                                 {
9323                                         float vertex[3];
9324                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9325                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9326                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9327                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9328                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9329                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9330                                         VectorNormalize(normal);
9331                                 }
9332                                 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);
9333                         }
9334                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9335                         rsurface.svector3f_bufferobject = 0;
9336                         rsurface.svector3f_bufferoffset = 0;
9337                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9338                         rsurface.tvector3f_bufferobject = 0;
9339                         rsurface.tvector3f_bufferoffset = 0;
9340                         rsurface.normal3f = rsurface.array_deformednormal3f;
9341                         rsurface.normal3f_bufferobject = 0;
9342                         rsurface.normal3f_bufferoffset = 0;
9343                         break;
9344                 case Q3DEFORM_WAVE:
9345                         // deform vertex array to make wavey water and flags and such
9346                         waveparms[0] = deform->waveparms[0];
9347                         waveparms[1] = deform->waveparms[1];
9348                         waveparms[2] = deform->waveparms[2];
9349                         waveparms[3] = deform->waveparms[3];
9350                         // this is how a divisor of vertex influence on deformation
9351                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9352                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9353                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9354                         {
9355                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9356                                 for (j = 0;j < surface->num_vertices;j++)
9357                                 {
9358                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9359                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9360                                         // if the wavefunc depends on time, evaluate it per-vertex
9361                                         if (waveparms[3])
9362                                         {
9363                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9364                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9365                                         }
9366                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9367                                 }
9368                         }
9369                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9370                         rsurface.vertex3f_bufferobject = 0;
9371                         rsurface.vertex3f_bufferoffset = 0;
9372                         break;
9373                 case Q3DEFORM_BULGE:
9374                         // deform vertex array to make the surface have moving bulges
9375                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9376                         {
9377                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9378                                 for (j = 0;j < surface->num_vertices;j++)
9379                                 {
9380                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9381                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9382                                 }
9383                         }
9384                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9385                         rsurface.vertex3f_bufferobject = 0;
9386                         rsurface.vertex3f_bufferoffset = 0;
9387                         break;
9388                 case Q3DEFORM_MOVE:
9389                         // deform vertex array
9390                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9391                         VectorScale(deform->parms, scale, waveparms);
9392                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9393                         {
9394                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9395                                 for (j = 0;j < surface->num_vertices;j++)
9396                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9397                         }
9398                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9399                         rsurface.vertex3f_bufferobject = 0;
9400                         rsurface.vertex3f_bufferoffset = 0;
9401                         break;
9402                 }
9403         }
9404         // generate texcoords based on the chosen texcoord source
9405         switch(rsurface.texture->tcgen.tcgen)
9406         {
9407         default:
9408         case Q3TCGEN_TEXTURE:
9409                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9410                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9411                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9412                 break;
9413         case Q3TCGEN_LIGHTMAP:
9414                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9415                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9416                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9417                 break;
9418         case Q3TCGEN_VECTOR:
9419                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9420                 {
9421                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9422                         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)
9423                         {
9424                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9425                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9426                         }
9427                 }
9428                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9429                 rsurface.texcoordtexture2f_bufferobject  = 0;
9430                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9431                 break;
9432         case Q3TCGEN_ENVIRONMENT:
9433                 // make environment reflections using a spheremap
9434                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9435                 {
9436                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9437                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9438                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9439                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9440                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9441                         {
9442                                 // identical to Q3A's method, but executed in worldspace so
9443                                 // carried models can be shiny too
9444
9445                                 float viewer[3], d, reflected[3], worldreflected[3];
9446
9447                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9448                                 // VectorNormalize(viewer);
9449
9450                                 d = DotProduct(normal, viewer);
9451
9452                                 reflected[0] = normal[0]*2*d - viewer[0];
9453                                 reflected[1] = normal[1]*2*d - viewer[1];
9454                                 reflected[2] = normal[2]*2*d - viewer[2];
9455                                 // note: this is proportinal to viewer, so we can normalize later
9456
9457                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9458                                 VectorNormalize(worldreflected);
9459
9460                                 // note: this sphere map only uses world x and z!
9461                                 // so positive and negative y will LOOK THE SAME.
9462                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9463                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9464                         }
9465                 }
9466                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9467                 rsurface.texcoordtexture2f_bufferobject  = 0;
9468                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9469                 break;
9470         }
9471         // the only tcmod that needs software vertex processing is turbulent, so
9472         // check for it here and apply the changes if needed
9473         // and we only support that as the first one
9474         // (handling a mixture of turbulent and other tcmods would be problematic
9475         //  without punting it entirely to a software path)
9476         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9477         {
9478                 amplitude = rsurface.texture->tcmods[0].parms[1];
9479                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9480                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9481                 {
9482                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9483                         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)
9484                         {
9485                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9486                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9487                         }
9488                 }
9489                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9490                 rsurface.texcoordtexture2f_bufferobject  = 0;
9491                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9492         }
9493         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9494         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9495         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9496         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9497 }
9498
9499 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9500 {
9501         int i, j;
9502         const msurface_t *surface = texturesurfacelist[0];
9503         const msurface_t *surface2;
9504         int firstvertex;
9505         int endvertex;
9506         int numvertices;
9507         int numtriangles;
9508         // TODO: lock all array ranges before render, rather than on each surface
9509         if (texturenumsurfaces == 1)
9510         {
9511                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9512                 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);
9513         }
9514         else if (r_batchmode.integer == 2)
9515         {
9516                 #define MAXBATCHTRIANGLES 4096
9517                 int batchtriangles = 0;
9518                 static int batchelements[MAXBATCHTRIANGLES*3];
9519                 for (i = 0;i < texturenumsurfaces;i = j)
9520                 {
9521                         surface = texturesurfacelist[i];
9522                         j = i + 1;
9523                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9524                         {
9525                                 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);
9526                                 continue;
9527                         }
9528                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9529                         batchtriangles = surface->num_triangles;
9530                         firstvertex = surface->num_firstvertex;
9531                         endvertex = surface->num_firstvertex + surface->num_vertices;
9532                         for (;j < texturenumsurfaces;j++)
9533                         {
9534                                 surface2 = texturesurfacelist[j];
9535                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9536                                         break;
9537                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9538                                 batchtriangles += surface2->num_triangles;
9539                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9540                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9541                         }
9542                         surface2 = texturesurfacelist[j-1];
9543                         numvertices = endvertex - firstvertex;
9544                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9545                 }
9546         }
9547         else if (r_batchmode.integer == 1)
9548         {
9549                 for (i = 0;i < texturenumsurfaces;i = j)
9550                 {
9551                         surface = texturesurfacelist[i];
9552                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9553                                 if (texturesurfacelist[j] != surface2)
9554                                         break;
9555                         surface2 = texturesurfacelist[j-1];
9556                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9557                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9558                         GL_LockArrays(surface->num_firstvertex, numvertices);
9559                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9560                 }
9561         }
9562         else
9563         {
9564                 for (i = 0;i < texturenumsurfaces;i++)
9565                 {
9566                         surface = texturesurfacelist[i];
9567                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9568                         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);
9569                 }
9570         }
9571 }
9572
9573 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9574 {
9575         switch(vid.renderpath)
9576         {
9577         case RENDERPATH_CGGL:
9578 #ifdef SUPPORTCG
9579                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9580                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9581 #endif
9582                 break;
9583         case RENDERPATH_GL20:
9584                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9585                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9586                 break;
9587         case RENDERPATH_GL13:
9588         case RENDERPATH_GL11:
9589                 R_Mesh_TexBind(0, surface->lightmaptexture);
9590                 break;
9591         }
9592 }
9593
9594 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9595 {
9596         // pick the closest matching water plane and bind textures
9597         int planeindex, vertexindex;
9598         float d, bestd;
9599         vec3_t vert;
9600         const float *v;
9601         r_waterstate_waterplane_t *p, *bestp;
9602         bestd = 0;
9603         bestp = NULL;
9604         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9605         {
9606                 d = 0;
9607                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9608                 {
9609                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9610                         d += fabs(PlaneDiff(vert, &p->plane));
9611                 }
9612                 if (bestd > d || !bestp)
9613                 {
9614                         bestd = d;
9615                         bestp = p;
9616                 }
9617         }
9618         switch(vid.renderpath)
9619         {
9620         case RENDERPATH_CGGL:
9621 #ifdef SUPPORTCG
9622                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9623                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9624 #endif
9625                 break;
9626         case RENDERPATH_GL20:
9627                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9628                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9629                 break;
9630         case RENDERPATH_GL13:
9631         case RENDERPATH_GL11:
9632                 break;
9633         }
9634 }
9635
9636 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9637 {
9638         int i;
9639         const msurface_t *surface;
9640         if (r_waterstate.renderingscene)
9641                 return;
9642         for (i = 0;i < texturenumsurfaces;i++)
9643         {
9644                 surface = texturesurfacelist[i];
9645                 RSurf_BindLightmapForSurface(surface);
9646                 RSurf_BindReflectionForSurface(surface);
9647                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9648                 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);
9649         }
9650 }
9651
9652 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9653 {
9654         int i;
9655         int j;
9656         const msurface_t *surface = texturesurfacelist[0];
9657         const msurface_t *surface2;
9658         int firstvertex;
9659         int endvertex;
9660         int numvertices;
9661         int numtriangles;
9662         if (texturenumsurfaces == 1)
9663         {
9664                 RSurf_BindLightmapForSurface(surface);
9665                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9666                 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);
9667         }
9668         else if (r_batchmode.integer == 2)
9669         {
9670 #define MAXBATCHTRIANGLES 4096
9671                 int batchtriangles = 0;
9672                 static int batchelements[MAXBATCHTRIANGLES*3];
9673                 for (i = 0;i < texturenumsurfaces;i = j)
9674                 {
9675                         surface = texturesurfacelist[i];
9676                         RSurf_BindLightmapForSurface(surface);
9677                         j = i + 1;
9678                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9679                         {
9680                                 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);
9681                                 continue;
9682                         }
9683                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9684                         batchtriangles = surface->num_triangles;
9685                         firstvertex = surface->num_firstvertex;
9686                         endvertex = surface->num_firstvertex + surface->num_vertices;
9687                         for (;j < texturenumsurfaces;j++)
9688                         {
9689                                 surface2 = texturesurfacelist[j];
9690                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9691                                         break;
9692                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9693                                 batchtriangles += surface2->num_triangles;
9694                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9695                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9696                         }
9697                         surface2 = texturesurfacelist[j-1];
9698                         numvertices = endvertex - firstvertex;
9699                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9700                 }
9701         }
9702         else if (r_batchmode.integer == 1)
9703         {
9704 #if 0
9705                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9706                 for (i = 0;i < texturenumsurfaces;i = j)
9707                 {
9708                         surface = texturesurfacelist[i];
9709                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9710                                 if (texturesurfacelist[j] != surface2)
9711                                         break;
9712                         Con_Printf(" %i", j - i);
9713                 }
9714                 Con_Printf("\n");
9715                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9716 #endif
9717                 for (i = 0;i < texturenumsurfaces;i = j)
9718                 {
9719                         surface = texturesurfacelist[i];
9720                         RSurf_BindLightmapForSurface(surface);
9721                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9722                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9723                                         break;
9724 #if 0
9725                         Con_Printf(" %i", j - i);
9726 #endif
9727                         surface2 = texturesurfacelist[j-1];
9728                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9729                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9730                         GL_LockArrays(surface->num_firstvertex, numvertices);
9731                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9732                 }
9733 #if 0
9734                 Con_Printf("\n");
9735 #endif
9736         }
9737         else
9738         {
9739                 for (i = 0;i < texturenumsurfaces;i++)
9740                 {
9741                         surface = texturesurfacelist[i];
9742                         RSurf_BindLightmapForSurface(surface);
9743                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9744                         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);
9745                 }
9746         }
9747 }
9748
9749 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9750 {
9751         int j;
9752         int texturesurfaceindex;
9753         if (r_showsurfaces.integer == 2)
9754         {
9755                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9756                 {
9757                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9758                         for (j = 0;j < surface->num_triangles;j++)
9759                         {
9760                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9761                                 GL_Color(f, f, f, 1);
9762                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9763                         }
9764                 }
9765         }
9766         else
9767         {
9768                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9769                 {
9770                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9771                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9772                         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);
9773                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9774                         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);
9775                 }
9776         }
9777 }
9778
9779 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9780 {
9781         int texturesurfaceindex;
9782         int i;
9783         const float *v;
9784         float *c2;
9785         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9786         {
9787                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9788                 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)
9789                 {
9790                         c2[0] = 0.5;
9791                         c2[1] = 0.5;
9792                         c2[2] = 0.5;
9793                         c2[3] = 1;
9794                 }
9795         }
9796         rsurface.lightmapcolor4f = rsurface.array_color4f;
9797         rsurface.lightmapcolor4f_bufferobject = 0;
9798         rsurface.lightmapcolor4f_bufferoffset = 0;
9799 }
9800
9801 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9802 {
9803         int texturesurfaceindex;
9804         int i;
9805         float f;
9806         const float *v;
9807         const float *c;
9808         float *c2;
9809         if (rsurface.lightmapcolor4f)
9810         {
9811                 // generate color arrays for the surfaces in this list
9812                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9813                 {
9814                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9815                         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)
9816                         {
9817                                 f = RSurf_FogVertex(v);
9818                                 c2[0] = c[0] * f;
9819                                 c2[1] = c[1] * f;
9820                                 c2[2] = c[2] * f;
9821                                 c2[3] = c[3];
9822                         }
9823                 }
9824         }
9825         else
9826         {
9827                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9828                 {
9829                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9830                         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)
9831                         {
9832                                 f = RSurf_FogVertex(v);
9833                                 c2[0] = f;
9834                                 c2[1] = f;
9835                                 c2[2] = f;
9836                                 c2[3] = 1;
9837                         }
9838                 }
9839         }
9840         rsurface.lightmapcolor4f = rsurface.array_color4f;
9841         rsurface.lightmapcolor4f_bufferobject = 0;
9842         rsurface.lightmapcolor4f_bufferoffset = 0;
9843 }
9844
9845 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9846 {
9847         int texturesurfaceindex;
9848         int i;
9849         float f;
9850         const float *v;
9851         const float *c;
9852         float *c2;
9853         if (!rsurface.lightmapcolor4f)
9854                 return;
9855         // generate color arrays for the surfaces in this list
9856         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9857         {
9858                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9859                 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)
9860                 {
9861                         f = RSurf_FogVertex(v);
9862                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9863                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9864                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9865                         c2[3] = c[3];
9866                 }
9867         }
9868         rsurface.lightmapcolor4f = rsurface.array_color4f;
9869         rsurface.lightmapcolor4f_bufferobject = 0;
9870         rsurface.lightmapcolor4f_bufferoffset = 0;
9871 }
9872
9873 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
9874 {
9875         int texturesurfaceindex;
9876         int i;
9877         const float *c;
9878         float *c2;
9879         if (!rsurface.lightmapcolor4f)
9880                 return;
9881         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9882         {
9883                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9884                 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)
9885                 {
9886                         c2[0] = c[0] * r;
9887                         c2[1] = c[1] * g;
9888                         c2[2] = c[2] * b;
9889                         c2[3] = c[3] * a;
9890                 }
9891         }
9892         rsurface.lightmapcolor4f = rsurface.array_color4f;
9893         rsurface.lightmapcolor4f_bufferobject = 0;
9894         rsurface.lightmapcolor4f_bufferoffset = 0;
9895 }
9896
9897 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9898 {
9899         int texturesurfaceindex;
9900         int i;
9901         const float *c;
9902         float *c2;
9903         if (!rsurface.lightmapcolor4f)
9904                 return;
9905         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9906         {
9907                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9908                 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)
9909                 {
9910                         c2[0] = c[0] + r_refdef.scene.ambient;
9911                         c2[1] = c[1] + r_refdef.scene.ambient;
9912                         c2[2] = c[2] + r_refdef.scene.ambient;
9913                         c2[3] = c[3];
9914                 }
9915         }
9916         rsurface.lightmapcolor4f = rsurface.array_color4f;
9917         rsurface.lightmapcolor4f_bufferobject = 0;
9918         rsurface.lightmapcolor4f_bufferoffset = 0;
9919 }
9920
9921 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9922 {
9923         // TODO: optimize
9924         rsurface.lightmapcolor4f = NULL;
9925         rsurface.lightmapcolor4f_bufferobject = 0;
9926         rsurface.lightmapcolor4f_bufferoffset = 0;
9927         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9928         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9929         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9930         GL_Color(r, g, b, a);
9931         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
9932 }
9933
9934 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9935 {
9936         // TODO: optimize applyfog && applycolor case
9937         // just apply fog if necessary, and tint the fog color array if necessary
9938         rsurface.lightmapcolor4f = NULL;
9939         rsurface.lightmapcolor4f_bufferobject = 0;
9940         rsurface.lightmapcolor4f_bufferoffset = 0;
9941         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9942         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9943         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9944         GL_Color(r, g, b, a);
9945         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9946 }
9947
9948 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9949 {
9950         int texturesurfaceindex;
9951         int i;
9952         float *c;
9953         // TODO: optimize
9954         if (texturesurfacelist[0]->lightmapinfo)
9955         {
9956                 // generate color arrays for the surfaces in this list
9957                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9958                 {
9959                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9960                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
9961                         {
9962                                 if (surface->lightmapinfo->samples)
9963                                 {
9964                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
9965                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
9966                                         VectorScale(lm, scale, c);
9967                                         if (surface->lightmapinfo->styles[1] != 255)
9968                                         {
9969                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9970                                                 lm += size3;
9971                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
9972                                                 VectorMA(c, scale, lm, c);
9973                                                 if (surface->lightmapinfo->styles[2] != 255)
9974                                                 {
9975                                                         lm += size3;
9976                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
9977                                                         VectorMA(c, scale, lm, c);
9978                                                         if (surface->lightmapinfo->styles[3] != 255)
9979                                                         {
9980                                                                 lm += size3;
9981                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
9982                                                                 VectorMA(c, scale, lm, c);
9983                                                         }
9984                                                 }
9985                                         }
9986                                 }
9987                                 else
9988                                         VectorClear(c);
9989                                 c[3] = 1;
9990                         }
9991                 }
9992                 rsurface.lightmapcolor4f = rsurface.array_color4f;
9993                 rsurface.lightmapcolor4f_bufferobject = 0;
9994                 rsurface.lightmapcolor4f_bufferoffset = 0;
9995         }
9996         else
9997         {
9998                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
9999                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10000                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10001         }
10002         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10003         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10004         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10005         GL_Color(r, g, b, a);
10006         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10007 }
10008
10009 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10010 {
10011         int texturesurfaceindex;
10012         int i;
10013         float f;
10014         float alpha;
10015         const float *v;
10016         const float *n;
10017         float *c;
10018         vec3_t ambientcolor;
10019         vec3_t diffusecolor;
10020         vec3_t lightdir;
10021         // TODO: optimize
10022         // model lighting
10023         VectorCopy(rsurface.modellight_lightdir, lightdir);
10024         f = 0.5f * r_refdef.lightmapintensity;
10025         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10026         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10027         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10028         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10029         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10030         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10031         alpha = *a;
10032         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10033         {
10034                 // generate color arrays for the surfaces in this list
10035                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10036                 {
10037                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10038                         int numverts = surface->num_vertices;
10039                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10040                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10041                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10042                         // q3-style directional shading
10043                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10044                         {
10045                                 if ((f = DotProduct(n, lightdir)) > 0)
10046                                         VectorMA(ambientcolor, f, diffusecolor, c);
10047                                 else
10048                                         VectorCopy(ambientcolor, c);
10049                                 c[3] = alpha;
10050                         }
10051                 }
10052                 *r = 1;
10053                 *g = 1;
10054                 *b = 1;
10055                 *a = 1;
10056                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10057                 rsurface.lightmapcolor4f_bufferobject = 0;
10058                 rsurface.lightmapcolor4f_bufferoffset = 0;
10059                 *applycolor = false;
10060         }
10061         else
10062         {
10063                 *r = ambientcolor[0];
10064                 *g = ambientcolor[1];
10065                 *b = ambientcolor[2];
10066                 rsurface.lightmapcolor4f = NULL;
10067                 rsurface.lightmapcolor4f_bufferobject = 0;
10068                 rsurface.lightmapcolor4f_bufferoffset = 0;
10069         }
10070 }
10071
10072 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10073 {
10074         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10075         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10076         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10077         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10078         GL_Color(r, g, b, a);
10079         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10080 }
10081
10082 void RSurf_SetupDepthAndCulling(void)
10083 {
10084         // submodels are biased to avoid z-fighting with world surfaces that they
10085         // may be exactly overlapping (avoids z-fighting artifacts on certain
10086         // doors and things in Quake maps)
10087         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10088         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10089         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10090         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10091 }
10092
10093 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10094 {
10095         // transparent sky would be ridiculous
10096         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10097                 return;
10098         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10099         skyrenderlater = true;
10100         RSurf_SetupDepthAndCulling();
10101         GL_DepthMask(true);
10102         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10103         // skymasking on them, and Quake3 never did sky masking (unlike
10104         // software Quake and software Quake2), so disable the sky masking
10105         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10106         // and skymasking also looks very bad when noclipping outside the
10107         // level, so don't use it then either.
10108         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10109         {
10110                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10111                 R_Mesh_ColorPointer(NULL, 0, 0);
10112                 R_Mesh_ResetTextureState();
10113                 if (skyrendermasked)
10114                 {
10115                         R_SetupShader_DepthOrShadow();
10116                         // depth-only (masking)
10117                         GL_ColorMask(0,0,0,0);
10118                         // just to make sure that braindead drivers don't draw
10119                         // anything despite that colormask...
10120                         GL_BlendFunc(GL_ZERO, GL_ONE);
10121                 }
10122                 else
10123                 {
10124                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10125                         // fog sky
10126                         GL_BlendFunc(GL_ONE, GL_ZERO);
10127                 }
10128                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10129                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10130                 if (skyrendermasked)
10131                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10132         }
10133         R_Mesh_ResetTextureState();
10134         GL_Color(1, 1, 1, 1);
10135 }
10136
10137 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10138 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10139 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10140 {
10141         qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
10142         qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
10143
10144         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10145                 return;
10146
10147         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10148                 R_Mesh_ColorPointer(NULL, 0, 0);
10149         else
10150                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10151
10152         if (refract)
10153         {
10154                 // render background
10155                 GL_BlendFunc(GL_ONE, GL_ZERO);
10156                 GL_DepthMask(true);
10157                 GL_AlphaTest(false);
10158
10159                 GL_Color(1, 1, 1, 1);
10160                 R_Mesh_ColorPointer(NULL, 0, 0);
10161
10162                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10163                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10164                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10165                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10166                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10167                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10168                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10169                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10170                 GL_LockArrays(0, 0);
10171
10172                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10173                 GL_DepthMask(false);
10174                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10175                         R_Mesh_ColorPointer(NULL, 0, 0);
10176                 else
10177                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10178         }
10179
10180         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10181
10182         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10183         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10184         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10185         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10186         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10187         if (!prepass)
10188                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10189
10190         if (refract)
10191                 GL_DepthMask(true);
10192         else
10193                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10194         GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10195         GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
10196
10197         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10198         {
10199                 if (refract || reflect)
10200                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10201                 else
10202                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10203         }
10204         else
10205         {
10206                 if (refract || reflect)
10207                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10208                 else
10209                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10210         }
10211         GL_LockArrays(0, 0);
10212 }
10213
10214 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10215 {
10216         // OpenGL 1.3 path - anything not completely ancient
10217         int texturesurfaceindex;
10218         qboolean applycolor;
10219         qboolean applyfog;
10220         int layerindex;
10221         const texturelayer_t *layer;
10222         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10223
10224         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10225         {
10226                 vec4_t layercolor;
10227                 int layertexrgbscale;
10228                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10229                 {
10230                         if (layerindex == 0)
10231                                 GL_AlphaTest(true);
10232                         else
10233                         {
10234                                 GL_AlphaTest(false);
10235                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10236                         }
10237                 }
10238                 GL_DepthMask(layer->depthmask && writedepth);
10239                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10240                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10241                 {
10242                         layertexrgbscale = 4;
10243                         VectorScale(layer->color, 0.25f, layercolor);
10244                 }
10245                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10246                 {
10247                         layertexrgbscale = 2;
10248                         VectorScale(layer->color, 0.5f, layercolor);
10249                 }
10250                 else
10251                 {
10252                         layertexrgbscale = 1;
10253                         VectorScale(layer->color, 1.0f, layercolor);
10254                 }
10255                 layercolor[3] = layer->color[3];
10256                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10257                 R_Mesh_ColorPointer(NULL, 0, 0);
10258                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10259                 switch (layer->type)
10260                 {
10261                 case TEXTURELAYERTYPE_LITTEXTURE:
10262                         // single-pass lightmapped texture with 2x rgbscale
10263                         //R_Mesh_TexBind(0, r_texture_white);
10264                         R_Mesh_TexMatrix(0, NULL);
10265                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10266                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10267                         R_Mesh_TexBind(1, layer->texture);
10268                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10269                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10270                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10271                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10272                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10273                         else if (rsurface.uselightmaptexture)
10274                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10275                         else
10276                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10277                         break;
10278                 case TEXTURELAYERTYPE_TEXTURE:
10279                         // singletexture unlit texture with transparency support
10280                         R_Mesh_TexBind(0, layer->texture);
10281                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10282                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10283                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10284                         R_Mesh_TexBind(1, 0);
10285                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10286                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10287                         break;
10288                 case TEXTURELAYERTYPE_FOG:
10289                         // singletexture fogging
10290                         if (layer->texture)
10291                         {
10292                                 R_Mesh_TexBind(0, layer->texture);
10293                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10294                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10295                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10296                         }
10297                         else
10298                         {
10299                                 R_Mesh_TexBind(0, 0);
10300                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10301                         }
10302                         R_Mesh_TexBind(1, 0);
10303                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10304                         // generate a color array for the fog pass
10305                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10306                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10307                         {
10308                                 int i;
10309                                 float f;
10310                                 const float *v;
10311                                 float *c;
10312                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10313                                 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)
10314                                 {
10315                                         f = 1 - RSurf_FogVertex(v);
10316                                         c[0] = layercolor[0];
10317                                         c[1] = layercolor[1];
10318                                         c[2] = layercolor[2];
10319                                         c[3] = f * layercolor[3];
10320                                 }
10321                         }
10322                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10323                         break;
10324                 default:
10325                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10326                 }
10327                 GL_LockArrays(0, 0);
10328         }
10329         CHECKGLERROR
10330         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10331         {
10332                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10333                 GL_AlphaTest(false);
10334         }
10335 }
10336
10337 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10338 {
10339         // OpenGL 1.1 - crusty old voodoo path
10340         int texturesurfaceindex;
10341         qboolean applyfog;
10342         int layerindex;
10343         const texturelayer_t *layer;
10344         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10345
10346         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10347         {
10348                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10349                 {
10350                         if (layerindex == 0)
10351                                 GL_AlphaTest(true);
10352                         else
10353                         {
10354                                 GL_AlphaTest(false);
10355                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10356                         }
10357                 }
10358                 GL_DepthMask(layer->depthmask && writedepth);
10359                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10360                 R_Mesh_ColorPointer(NULL, 0, 0);
10361                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10362                 switch (layer->type)
10363                 {
10364                 case TEXTURELAYERTYPE_LITTEXTURE:
10365                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10366                         {
10367                                 // two-pass lit texture with 2x rgbscale
10368                                 // first the lightmap pass
10369                                 //R_Mesh_TexBind(0, r_texture_white);
10370                                 R_Mesh_TexMatrix(0, NULL);
10371                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10372                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10373                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10374                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10375                                 else if (rsurface.uselightmaptexture)
10376                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10377                                 else
10378                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10379                                 GL_LockArrays(0, 0);
10380                                 // then apply the texture to it
10381                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10382                                 R_Mesh_TexBind(0, layer->texture);
10383                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10384                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10385                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10386                                 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);
10387                         }
10388                         else
10389                         {
10390                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10391                                 R_Mesh_TexBind(0, layer->texture);
10392                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10393                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10394                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10395                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10396                                         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);
10397                                 else
10398                                         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);
10399                         }
10400                         break;
10401                 case TEXTURELAYERTYPE_TEXTURE:
10402                         // singletexture unlit texture with transparency support
10403                         R_Mesh_TexBind(0, layer->texture);
10404                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10405                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10406                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10407                         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);
10408                         break;
10409                 case TEXTURELAYERTYPE_FOG:
10410                         // singletexture fogging
10411                         if (layer->texture)
10412                         {
10413                                 R_Mesh_TexBind(0, layer->texture);
10414                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10415                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10416                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10417                         }
10418                         else
10419                         {
10420                                 R_Mesh_TexBind(0, 0);
10421                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10422                         }
10423                         // generate a color array for the fog pass
10424                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10425                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10426                         {
10427                                 int i;
10428                                 float f;
10429                                 const float *v;
10430                                 float *c;
10431                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10432                                 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)
10433                                 {
10434                                         f = 1 - RSurf_FogVertex(v);
10435                                         c[0] = layer->color[0];
10436                                         c[1] = layer->color[1];
10437                                         c[2] = layer->color[2];
10438                                         c[3] = f * layer->color[3];
10439                                 }
10440                         }
10441                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10442                         break;
10443                 default:
10444                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10445                 }
10446                 GL_LockArrays(0, 0);
10447         }
10448         CHECKGLERROR
10449         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10450         {
10451                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10452                 GL_AlphaTest(false);
10453         }
10454 }
10455
10456 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10457 {
10458         float c[4];
10459
10460         GL_AlphaTest(false);
10461         R_Mesh_ColorPointer(NULL, 0, 0);
10462         R_Mesh_ResetTextureState();
10463         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10464
10465         if(rsurface.texture && rsurface.texture->currentskinframe)
10466         {
10467                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10468                 c[3] *= rsurface.texture->currentalpha;
10469         }
10470         else
10471         {
10472                 c[0] = 1;
10473                 c[1] = 0;
10474                 c[2] = 1;
10475                 c[3] = 1;
10476         }
10477
10478         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10479         {
10480                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10481                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10482                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10483         }
10484
10485         // brighten it up (as texture value 127 means "unlit")
10486         c[0] *= 2 * r_refdef.view.colorscale;
10487         c[1] *= 2 * r_refdef.view.colorscale;
10488         c[2] *= 2 * r_refdef.view.colorscale;
10489
10490         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10491                 c[3] *= r_wateralpha.value;
10492
10493         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10494         {
10495                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10496                 GL_DepthMask(false);
10497         }
10498         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10499         {
10500                 GL_BlendFunc(GL_ONE, GL_ONE);
10501                 GL_DepthMask(false);
10502         }
10503         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10504         {
10505                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10506                 GL_DepthMask(false);
10507         }
10508         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10509         {
10510                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10511                 GL_DepthMask(false);
10512         }
10513         else
10514         {
10515                 GL_BlendFunc(GL_ONE, GL_ZERO);
10516                 GL_DepthMask(writedepth);
10517         }
10518
10519         rsurface.lightmapcolor4f = NULL;
10520
10521         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10522         {
10523                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10524
10525                 rsurface.lightmapcolor4f = NULL;
10526                 rsurface.lightmapcolor4f_bufferobject = 0;
10527                 rsurface.lightmapcolor4f_bufferoffset = 0;
10528         }
10529         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10530         {
10531                 qboolean applycolor = true;
10532                 float one = 1.0;
10533
10534                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10535
10536                 r_refdef.lightmapintensity = 1;
10537                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10538                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10539         }
10540         else
10541         {
10542                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10543
10544                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10545                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10546                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10547         }
10548
10549         if(!rsurface.lightmapcolor4f)
10550                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10551
10552         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10553         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10554         if(r_refdef.fogenabled)
10555                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10556
10557         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10558         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10559 }
10560
10561 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10562 {
10563         CHECKGLERROR
10564         RSurf_SetupDepthAndCulling();
10565         if (r_showsurfaces.integer == 3 && !prepass)
10566         {
10567                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10568                 return;
10569         }
10570         switch (vid.renderpath)
10571         {
10572         case RENDERPATH_GL20:
10573         case RENDERPATH_CGGL:
10574                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10575                 break;
10576         case RENDERPATH_GL13:
10577                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10578                 break;
10579         case RENDERPATH_GL11:
10580                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10581                 break;
10582         }
10583         CHECKGLERROR
10584 }
10585
10586 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10587 {
10588         CHECKGLERROR
10589         RSurf_SetupDepthAndCulling();
10590         if (r_showsurfaces.integer == 3 && !prepass)
10591         {
10592                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10593                 return;
10594         }
10595         switch (vid.renderpath)
10596         {
10597         case RENDERPATH_GL20:
10598         case RENDERPATH_CGGL:
10599                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10600                 break;
10601         case RENDERPATH_GL13:
10602                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10603                 break;
10604         case RENDERPATH_GL11:
10605                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10606                 break;
10607         }
10608         CHECKGLERROR
10609 }
10610
10611 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10612 {
10613         int i, j;
10614         int texturenumsurfaces, endsurface;
10615         texture_t *texture;
10616         const msurface_t *surface;
10617         const msurface_t *texturesurfacelist[256];
10618
10619         // if the model is static it doesn't matter what value we give for
10620         // wantnormals and wanttangents, so this logic uses only rules applicable
10621         // to a model, knowing that they are meaningless otherwise
10622         if (ent == r_refdef.scene.worldentity)
10623                 RSurf_ActiveWorldEntity();
10624         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10625                 RSurf_ActiveModelEntity(ent, false, false, false);
10626         else
10627         {
10628                 switch (vid.renderpath)
10629                 {
10630                 case RENDERPATH_GL20:
10631                 case RENDERPATH_CGGL:
10632                         RSurf_ActiveModelEntity(ent, true, true, false);
10633                         break;
10634                 case RENDERPATH_GL13:
10635                 case RENDERPATH_GL11:
10636                         RSurf_ActiveModelEntity(ent, true, false, false);
10637                         break;
10638                 }
10639         }
10640
10641         if (r_transparentdepthmasking.integer)
10642         {
10643                 qboolean setup = false;
10644                 for (i = 0;i < numsurfaces;i = j)
10645                 {
10646                         j = i + 1;
10647                         surface = rsurface.modelsurfaces + surfacelist[i];
10648                         texture = surface->texture;
10649                         rsurface.texture = R_GetCurrentTexture(texture);
10650                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10651                         // scan ahead until we find a different texture
10652                         endsurface = min(i + 1024, numsurfaces);
10653                         texturenumsurfaces = 0;
10654                         texturesurfacelist[texturenumsurfaces++] = surface;
10655                         for (;j < endsurface;j++)
10656                         {
10657                                 surface = rsurface.modelsurfaces + surfacelist[j];
10658                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10659                                         break;
10660                                 texturesurfacelist[texturenumsurfaces++] = surface;
10661                         }
10662                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10663                                 continue;
10664                         // render the range of surfaces as depth
10665                         if (!setup)
10666                         {
10667                                 setup = true;
10668                                 GL_ColorMask(0,0,0,0);
10669                                 GL_Color(1,1,1,1);
10670                                 GL_DepthTest(true);
10671                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10672                                 GL_DepthMask(true);
10673                                 GL_AlphaTest(false);
10674                                 R_Mesh_ColorPointer(NULL, 0, 0);
10675                                 R_Mesh_ResetTextureState();
10676                                 R_SetupShader_DepthOrShadow();
10677                         }
10678                         RSurf_SetupDepthAndCulling();
10679                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10680                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10681                 }
10682                 if (setup)
10683                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10684         }
10685
10686         for (i = 0;i < numsurfaces;i = j)
10687         {
10688                 j = i + 1;
10689                 surface = rsurface.modelsurfaces + surfacelist[i];
10690                 texture = surface->texture;
10691                 rsurface.texture = R_GetCurrentTexture(texture);
10692                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10693                 // scan ahead until we find a different texture
10694                 endsurface = min(i + 1024, numsurfaces);
10695                 texturenumsurfaces = 0;
10696                 texturesurfacelist[texturenumsurfaces++] = surface;
10697                 for (;j < endsurface;j++)
10698                 {
10699                         surface = rsurface.modelsurfaces + surfacelist[j];
10700                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10701                                 break;
10702                         texturesurfacelist[texturenumsurfaces++] = surface;
10703                 }
10704                 // render the range of surfaces
10705                 if (ent == r_refdef.scene.worldentity)
10706                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10707                 else
10708                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10709         }
10710         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10711         GL_AlphaTest(false);
10712 }
10713
10714 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10715 {
10716         // transparent surfaces get pushed off into the transparent queue
10717         int surfacelistindex;
10718         const msurface_t *surface;
10719         vec3_t tempcenter, center;
10720         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10721         {
10722                 surface = texturesurfacelist[surfacelistindex];
10723                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10724                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10725                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10726                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10727                 if (queueentity->transparent_offset) // transparent offset
10728                 {
10729                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10730                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10731                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10732                 }
10733                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10734         }
10735 }
10736
10737 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10738 {
10739         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10740         CHECKGLERROR
10741         if (depthonly)
10742         {
10743                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10744                         return;
10745                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10746                         return;
10747                 RSurf_SetupDepthAndCulling();
10748                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10749                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10750         }
10751         else if (prepass)
10752         {
10753                 if (!rsurface.texture->currentnumlayers)
10754                         return;
10755                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10756                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10757                 else
10758                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10759         }
10760         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10761         {
10762                 RSurf_SetupDepthAndCulling();
10763                 GL_AlphaTest(false);
10764                 R_Mesh_ColorPointer(NULL, 0, 0);
10765                 R_Mesh_ResetTextureState();
10766                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10767                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10768                 GL_DepthMask(true);
10769                 GL_BlendFunc(GL_ONE, GL_ZERO);
10770                 GL_Color(0, 0, 0, 1);
10771                 GL_DepthTest(writedepth);
10772                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10773         }
10774         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10775         {
10776                 RSurf_SetupDepthAndCulling();
10777                 GL_AlphaTest(false);
10778                 R_Mesh_ColorPointer(NULL, 0, 0);
10779                 R_Mesh_ResetTextureState();
10780                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10781                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10782                 GL_DepthMask(true);
10783                 GL_BlendFunc(GL_ONE, GL_ZERO);
10784                 GL_DepthTest(true);
10785                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10786         }
10787         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10788                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10789         else if (!rsurface.texture->currentnumlayers)
10790                 return;
10791         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10792         {
10793                 // in the deferred case, transparent surfaces were queued during prepass
10794                 if (!r_shadow_usingdeferredprepass)
10795                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10796         }
10797         else
10798         {
10799                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10800                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10801         }
10802         CHECKGLERROR
10803 }
10804
10805 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10806 {
10807         int i, j;
10808         texture_t *texture;
10809         // break the surface list down into batches by texture and use of lightmapping
10810         for (i = 0;i < numsurfaces;i = j)
10811         {
10812                 j = i + 1;
10813                 // texture is the base texture pointer, rsurface.texture is the
10814                 // current frame/skin the texture is directing us to use (for example
10815                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10816                 // use skin 1 instead)
10817                 texture = surfacelist[i]->texture;
10818                 rsurface.texture = R_GetCurrentTexture(texture);
10819                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10820                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10821                 {
10822                         // if this texture is not the kind we want, skip ahead to the next one
10823                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10824                                 ;
10825                         continue;
10826                 }
10827                 // simply scan ahead until we find a different texture or lightmap state
10828                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10829                         ;
10830                 // render the range of surfaces
10831                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10832         }
10833 }
10834
10835 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10836 {
10837         CHECKGLERROR
10838         if (depthonly)
10839         {
10840                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10841                         return;
10842                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10843                         return;
10844                 RSurf_SetupDepthAndCulling();
10845                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10846                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10847         }
10848         else if (prepass)
10849         {
10850                 if (!rsurface.texture->currentnumlayers)
10851                         return;
10852                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10853                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10854                 else
10855                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10856         }
10857         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10858         {
10859                 RSurf_SetupDepthAndCulling();
10860                 GL_AlphaTest(false);
10861                 R_Mesh_ColorPointer(NULL, 0, 0);
10862                 R_Mesh_ResetTextureState();
10863                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10864                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10865                 GL_DepthMask(true);
10866                 GL_BlendFunc(GL_ONE, GL_ZERO);
10867                 GL_Color(0, 0, 0, 1);
10868                 GL_DepthTest(writedepth);
10869                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10870         }
10871         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10872         {
10873                 RSurf_SetupDepthAndCulling();
10874                 GL_AlphaTest(false);
10875                 R_Mesh_ColorPointer(NULL, 0, 0);
10876                 R_Mesh_ResetTextureState();
10877                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10878                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10879                 GL_DepthMask(true);
10880                 GL_BlendFunc(GL_ONE, GL_ZERO);
10881                 GL_DepthTest(true);
10882                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10883         }
10884         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10885                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10886         else if (!rsurface.texture->currentnumlayers)
10887                 return;
10888         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10889         {
10890                 // in the deferred case, transparent surfaces were queued during prepass
10891                 if (!r_shadow_usingdeferredprepass)
10892                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10893         }
10894         else
10895         {
10896                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10897                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10898         }
10899         CHECKGLERROR
10900 }
10901
10902 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10903 {
10904         int i, j;
10905         texture_t *texture;
10906         // break the surface list down into batches by texture and use of lightmapping
10907         for (i = 0;i < numsurfaces;i = j)
10908         {
10909                 j = i + 1;
10910                 // texture is the base texture pointer, rsurface.texture is the
10911                 // current frame/skin the texture is directing us to use (for example
10912                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10913                 // use skin 1 instead)
10914                 texture = surfacelist[i]->texture;
10915                 rsurface.texture = R_GetCurrentTexture(texture);
10916                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10917                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10918                 {
10919                         // if this texture is not the kind we want, skip ahead to the next one
10920                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10921                                 ;
10922                         continue;
10923                 }
10924                 // simply scan ahead until we find a different texture or lightmap state
10925                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10926                         ;
10927                 // render the range of surfaces
10928                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10929         }
10930 }
10931
10932 float locboxvertex3f[6*4*3] =
10933 {
10934         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10935         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10936         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10937         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10938         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10939         1,0,0, 0,0,0, 0,1,0, 1,1,0
10940 };
10941
10942 unsigned short locboxelements[6*2*3] =
10943 {
10944          0, 1, 2, 0, 2, 3,
10945          4, 5, 6, 4, 6, 7,
10946          8, 9,10, 8,10,11,
10947         12,13,14, 12,14,15,
10948         16,17,18, 16,18,19,
10949         20,21,22, 20,22,23
10950 };
10951
10952 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10953 {
10954         int i, j;
10955         cl_locnode_t *loc = (cl_locnode_t *)ent;
10956         vec3_t mins, size;
10957         float vertex3f[6*4*3];
10958         CHECKGLERROR
10959         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10960         GL_DepthMask(false);
10961         GL_DepthRange(0, 1);
10962         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10963         GL_DepthTest(true);
10964         GL_CullFace(GL_NONE);
10965         R_EntityMatrix(&identitymatrix);
10966
10967         R_Mesh_VertexPointer(vertex3f, 0, 0);
10968         R_Mesh_ColorPointer(NULL, 0, 0);
10969         R_Mesh_ResetTextureState();
10970         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10971
10972         i = surfacelist[0];
10973         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10974                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10975                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10976                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10977
10978         if (VectorCompare(loc->mins, loc->maxs))
10979         {
10980                 VectorSet(size, 2, 2, 2);
10981                 VectorMA(loc->mins, -0.5f, size, mins);
10982         }
10983         else
10984         {
10985                 VectorCopy(loc->mins, mins);
10986                 VectorSubtract(loc->maxs, loc->mins, size);
10987         }
10988
10989         for (i = 0;i < 6*4*3;)
10990                 for (j = 0;j < 3;j++, i++)
10991                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10992
10993         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
10994 }
10995
10996 void R_DrawLocs(void)
10997 {
10998         int index;
10999         cl_locnode_t *loc, *nearestloc;
11000         vec3_t center;
11001         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11002         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11003         {
11004                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11005                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11006         }
11007 }
11008
11009 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11010 {
11011         if (decalsystem->decals)
11012                 Mem_Free(decalsystem->decals);
11013         memset(decalsystem, 0, sizeof(*decalsystem));
11014 }
11015
11016 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)
11017 {
11018         tridecal_t *decal;
11019         tridecal_t *decals;
11020         int i;
11021         int maxdecals;
11022
11023         // expand or initialize the system
11024         if (decalsystem->maxdecals <= decalsystem->numdecals)
11025         {
11026                 decalsystem_t old = *decalsystem;
11027                 qboolean useshortelements;
11028                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11029                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11030                 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)));
11031                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11032                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11033                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11034                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11035                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11036                 if (decalsystem->numdecals)
11037                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11038                 if (old.decals)
11039                         Mem_Free(old.decals);
11040                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11041                         decalsystem->element3i[i] = i;
11042                 if (useshortelements)
11043                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11044                                 decalsystem->element3s[i] = i;
11045         }
11046
11047         // grab a decal and search for another free slot for the next one
11048         maxdecals = decalsystem->maxdecals;
11049         decals = decalsystem->decals;
11050         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11051         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11052                 ;
11053         decalsystem->freedecal = i;
11054         if (decalsystem->numdecals <= i)
11055                 decalsystem->numdecals = i + 1;
11056
11057         // initialize the decal
11058         decal->lived = 0;
11059         decal->triangleindex = triangleindex;
11060         decal->surfaceindex = surfaceindex;
11061         decal->decalsequence = decalsequence;
11062         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11063         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11064         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11065         decal->color4ub[0][3] = 255;
11066         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11067         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11068         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11069         decal->color4ub[1][3] = 255;
11070         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11071         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11072         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11073         decal->color4ub[2][3] = 255;
11074         decal->vertex3f[0][0] = v0[0];
11075         decal->vertex3f[0][1] = v0[1];
11076         decal->vertex3f[0][2] = v0[2];
11077         decal->vertex3f[1][0] = v1[0];
11078         decal->vertex3f[1][1] = v1[1];
11079         decal->vertex3f[1][2] = v1[2];
11080         decal->vertex3f[2][0] = v2[0];
11081         decal->vertex3f[2][1] = v2[1];
11082         decal->vertex3f[2][2] = v2[2];
11083         decal->texcoord2f[0][0] = t0[0];
11084         decal->texcoord2f[0][1] = t0[1];
11085         decal->texcoord2f[1][0] = t1[0];
11086         decal->texcoord2f[1][1] = t1[1];
11087         decal->texcoord2f[2][0] = t2[0];
11088         decal->texcoord2f[2][1] = t2[1];
11089 }
11090
11091 extern cvar_t cl_decals_bias;
11092 extern cvar_t cl_decals_models;
11093 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11094 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)
11095 {
11096         matrix4x4_t projection;
11097         decalsystem_t *decalsystem;
11098         qboolean dynamic;
11099         dp_model_t *model;
11100         const float *vertex3f;
11101         const msurface_t *surface;
11102         const msurface_t *surfaces;
11103         const int *surfacelist;
11104         const texture_t *texture;
11105         int numvertices;
11106         int numtriangles;
11107         int numsurfacelist;
11108         int surfacelistindex;
11109         int surfaceindex;
11110         int triangleindex;
11111         int decalsurfaceindex;
11112         int cornerindex;
11113         int index;
11114         int numpoints;
11115         const int *e;
11116         float localorigin[3];
11117         float localnormal[3];
11118         float localmins[3];
11119         float localmaxs[3];
11120         float localsize;
11121         float ilocalsize;
11122         float v[9][3];
11123         float tc[9][2];
11124         float c[9][4];
11125         //float normal[3];
11126         float planes[6][4];
11127         float f;
11128         float points[2][9][3];
11129         float angles[3];
11130         float temp[3];
11131
11132         decalsystem = &ent->decalsystem;
11133         model = ent->model;
11134         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11135         {
11136                 R_DecalSystem_Reset(&ent->decalsystem);
11137                 return;
11138         }
11139
11140         if (!model->brush.data_nodes && !cl_decals_models.integer)
11141         {
11142                 if (decalsystem->model)
11143                         R_DecalSystem_Reset(decalsystem);
11144                 return;
11145         }
11146
11147         if (decalsystem->model != model)
11148                 R_DecalSystem_Reset(decalsystem);
11149         decalsystem->model = model;
11150
11151         RSurf_ActiveModelEntity(ent, false, false, false);
11152
11153         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11154         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11155         VectorNormalize(localnormal);
11156         localsize = worldsize*rsurface.inversematrixscale;
11157         ilocalsize = 1.0f / localsize;
11158         localmins[0] = localorigin[0] - localsize;
11159         localmins[1] = localorigin[1] - localsize;
11160         localmins[2] = localorigin[2] - localsize;
11161         localmaxs[0] = localorigin[0] + localsize;
11162         localmaxs[1] = localorigin[1] + localsize;
11163         localmaxs[2] = localorigin[2] + localsize;
11164
11165         //VectorCopy(localnormal, planes[4]);
11166         //VectorVectors(planes[4], planes[2], planes[0]);
11167         AnglesFromVectors(angles, localnormal, NULL, false);
11168         AngleVectors(angles, planes[0], planes[2], planes[4]);
11169         VectorNegate(planes[0], planes[1]);
11170         VectorNegate(planes[2], planes[3]);
11171         VectorNegate(planes[4], planes[5]);
11172         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11173         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11174         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11175         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11176         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11177         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11178
11179 #if 1
11180 // works
11181 {
11182         matrix4x4_t forwardprojection;
11183         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11184         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11185 }
11186 #else
11187 // broken
11188 {
11189         float projectionvector[4][3];
11190         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11191         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11192         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11193         projectionvector[0][0] = planes[0][0] * ilocalsize;
11194         projectionvector[0][1] = planes[1][0] * ilocalsize;
11195         projectionvector[0][2] = planes[2][0] * ilocalsize;
11196         projectionvector[1][0] = planes[0][1] * ilocalsize;
11197         projectionvector[1][1] = planes[1][1] * ilocalsize;
11198         projectionvector[1][2] = planes[2][1] * ilocalsize;
11199         projectionvector[2][0] = planes[0][2] * ilocalsize;
11200         projectionvector[2][1] = planes[1][2] * ilocalsize;
11201         projectionvector[2][2] = planes[2][2] * ilocalsize;
11202         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11203         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11204         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11205         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11206 }
11207 #endif
11208
11209         dynamic = model->surfmesh.isanimated;
11210         vertex3f = rsurface.modelvertex3f;
11211         numsurfacelist = model->nummodelsurfaces;
11212         surfacelist = model->sortedmodelsurfaces;
11213         surfaces = model->data_surfaces;
11214         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11215         {
11216                 surfaceindex = surfacelist[surfacelistindex];
11217                 surface = surfaces + surfaceindex;
11218                 // skip transparent surfaces
11219                 texture = surface->texture;
11220                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11221                         continue;
11222                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11223                         continue;
11224                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11225                         continue;
11226                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11227                 numvertices = surface->num_vertices;
11228                 numtriangles = surface->num_triangles;
11229                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11230                 {
11231                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11232                         {
11233                                 index = 3*e[cornerindex];
11234                                 VectorCopy(vertex3f + index, v[cornerindex]);
11235                         }
11236                         // cull backfaces
11237                         //TriangleNormal(v[0], v[1], v[2], normal);
11238                         //if (DotProduct(normal, localnormal) < 0.0f)
11239                         //      continue;
11240                         // clip by each of the box planes formed from the projection matrix
11241                         // if anything survives, we emit the decal
11242                         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]);
11243                         if (numpoints < 3)
11244                                 continue;
11245                         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]);
11246                         if (numpoints < 3)
11247                                 continue;
11248                         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]);
11249                         if (numpoints < 3)
11250                                 continue;
11251                         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]);
11252                         if (numpoints < 3)
11253                                 continue;
11254                         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]);
11255                         if (numpoints < 3)
11256                                 continue;
11257                         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]);
11258                         if (numpoints < 3)
11259                                 continue;
11260                         // some part of the triangle survived, so we have to accept it...
11261                         if (dynamic)
11262                         {
11263                                 // dynamic always uses the original triangle
11264                                 numpoints = 3;
11265                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11266                                 {
11267                                         index = 3*e[cornerindex];
11268                                         VectorCopy(vertex3f + index, v[cornerindex]);
11269                                 }
11270                         }
11271                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11272                         {
11273                                 // convert vertex positions to texcoords
11274                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11275                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11276                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11277                                 // calculate distance fade from the projection origin
11278                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11279                                 f = bound(0.0f, f, 1.0f);
11280                                 c[cornerindex][0] = r * f;
11281                                 c[cornerindex][1] = g * f;
11282                                 c[cornerindex][2] = b * f;
11283                                 c[cornerindex][3] = 1.0f;
11284                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11285                         }
11286                         if (dynamic)
11287                                 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);
11288                         else
11289                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11290                                         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);
11291                 }
11292         }
11293 }
11294
11295 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11296 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)
11297 {
11298         int renderentityindex;
11299         float worldmins[3];
11300         float worldmaxs[3];
11301         entity_render_t *ent;
11302
11303         if (!cl_decals_newsystem.integer)
11304                 return;
11305
11306         worldmins[0] = worldorigin[0] - worldsize;
11307         worldmins[1] = worldorigin[1] - worldsize;
11308         worldmins[2] = worldorigin[2] - worldsize;
11309         worldmaxs[0] = worldorigin[0] + worldsize;
11310         worldmaxs[1] = worldorigin[1] + worldsize;
11311         worldmaxs[2] = worldorigin[2] + worldsize;
11312
11313         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11314
11315         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11316         {
11317                 ent = r_refdef.scene.entities[renderentityindex];
11318                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11319                         continue;
11320
11321                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11322         }
11323 }
11324
11325 typedef struct r_decalsystem_splatqueue_s
11326 {
11327         vec3_t worldorigin;
11328         vec3_t worldnormal;
11329         float color[4];
11330         float tcrange[4];
11331         float worldsize;
11332         int decalsequence;
11333 }
11334 r_decalsystem_splatqueue_t;
11335
11336 int r_decalsystem_numqueued = 0;
11337 #define MAX_DECALSYSTEM_QUEUE 1024
11338 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11339
11340 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)
11341 {
11342         r_decalsystem_splatqueue_t *queue;
11343
11344         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11345                 return;
11346
11347         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11348         VectorCopy(worldorigin, queue->worldorigin);
11349         VectorCopy(worldnormal, queue->worldnormal);
11350         Vector4Set(queue->color, r, g, b, a);
11351         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11352         queue->worldsize = worldsize;
11353         queue->decalsequence = cl.decalsequence++;
11354 }
11355
11356 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11357 {
11358         int i;
11359         r_decalsystem_splatqueue_t *queue;
11360
11361         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11362                 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);
11363         r_decalsystem_numqueued = 0;
11364 }
11365
11366 extern cvar_t cl_decals_max;
11367 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11368 {
11369         int i;
11370         decalsystem_t *decalsystem = &ent->decalsystem;
11371         int numdecals;
11372         int killsequence;
11373         tridecal_t *decal;
11374         float frametime;
11375         float lifetime;
11376
11377         if (!decalsystem->numdecals)
11378                 return;
11379
11380         if (r_showsurfaces.integer)
11381                 return;
11382
11383         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11384         {
11385                 R_DecalSystem_Reset(decalsystem);
11386                 return;
11387         }
11388
11389         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11390         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11391
11392         if (decalsystem->lastupdatetime)
11393                 frametime = (cl.time - decalsystem->lastupdatetime);
11394         else
11395                 frametime = 0;
11396         decalsystem->lastupdatetime = cl.time;
11397         decal = decalsystem->decals;
11398         numdecals = decalsystem->numdecals;
11399
11400         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11401         {
11402                 if (decal->color4ub[0][3])
11403                 {
11404                         decal->lived += frametime;
11405                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11406                         {
11407                                 memset(decal, 0, sizeof(*decal));
11408                                 if (decalsystem->freedecal > i)
11409                                         decalsystem->freedecal = i;
11410                         }
11411                 }
11412         }
11413         decal = decalsystem->decals;
11414         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11415                 numdecals--;
11416
11417         // collapse the array by shuffling the tail decals into the gaps
11418         for (;;)
11419         {
11420                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11421                         decalsystem->freedecal++;
11422                 if (decalsystem->freedecal == numdecals)
11423                         break;
11424                 decal[decalsystem->freedecal] = decal[--numdecals];
11425         }
11426
11427         decalsystem->numdecals = numdecals;
11428
11429         if (numdecals <= 0)
11430         {
11431                 // if there are no decals left, reset decalsystem
11432                 R_DecalSystem_Reset(decalsystem);
11433         }
11434 }
11435
11436 extern skinframe_t *decalskinframe;
11437 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11438 {
11439         int i;
11440         decalsystem_t *decalsystem = &ent->decalsystem;
11441         int numdecals;
11442         tridecal_t *decal;
11443         float fadedelay;
11444         float faderate;
11445         float alpha;
11446         float *v3f;
11447         float *c4f;
11448         float *t2f;
11449         const int *e;
11450         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11451         int numtris = 0;
11452
11453         numdecals = decalsystem->numdecals;
11454         if (!numdecals)
11455                 return;
11456
11457         if (r_showsurfaces.integer)
11458                 return;
11459
11460         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11461         {
11462                 R_DecalSystem_Reset(decalsystem);
11463                 return;
11464         }
11465
11466         // if the model is static it doesn't matter what value we give for
11467         // wantnormals and wanttangents, so this logic uses only rules applicable
11468         // to a model, knowing that they are meaningless otherwise
11469         if (ent == r_refdef.scene.worldentity)
11470                 RSurf_ActiveWorldEntity();
11471         else
11472                 RSurf_ActiveModelEntity(ent, false, false, false);
11473
11474         decalsystem->lastupdatetime = cl.time;
11475         decal = decalsystem->decals;
11476
11477         fadedelay = cl_decals_time.value;
11478         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11479
11480         // update vertex positions for animated models
11481         v3f = decalsystem->vertex3f;
11482         c4f = decalsystem->color4f;
11483         t2f = decalsystem->texcoord2f;
11484         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11485         {
11486                 if (!decal->color4ub[0][3])
11487                         continue;
11488
11489                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11490                         continue;
11491
11492                 // update color values for fading decals
11493                 if (decal->lived >= cl_decals_time.value)
11494                 {
11495                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11496                         alpha *= (1.0f/255.0f);
11497                 }
11498                 else
11499                         alpha = 1.0f/255.0f;
11500
11501                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11502                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11503                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11504                 c4f[ 3] = 1;
11505                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11506                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11507                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11508                 c4f[ 7] = 1;
11509                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11510                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11511                 c4f[10] = decal->color4ub[2][2] * alpha;
11512                 c4f[11] = 1;
11513
11514                 t2f[0] = decal->texcoord2f[0][0];
11515                 t2f[1] = decal->texcoord2f[0][1];
11516                 t2f[2] = decal->texcoord2f[1][0];
11517                 t2f[3] = decal->texcoord2f[1][1];
11518                 t2f[4] = decal->texcoord2f[2][0];
11519                 t2f[5] = decal->texcoord2f[2][1];
11520
11521                 // update vertex positions for animated models
11522                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11523                 {
11524                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11525                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11526                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11527                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11528                 }
11529                 else
11530                 {
11531                         VectorCopy(decal->vertex3f[0], v3f);
11532                         VectorCopy(decal->vertex3f[1], v3f + 3);
11533                         VectorCopy(decal->vertex3f[2], v3f + 6);
11534                 }
11535
11536                 v3f += 9;
11537                 c4f += 12;
11538                 t2f += 6;
11539                 numtris++;
11540         }
11541
11542         if (numtris > 0)
11543         {
11544                 r_refdef.stats.drawndecals += numtris;
11545
11546                 if (r_refdef.fogenabled)
11547                 {
11548                         switch(vid.renderpath)
11549                         {
11550                         case RENDERPATH_GL20:
11551                         case RENDERPATH_CGGL:
11552                         case RENDERPATH_GL13:
11553                         case RENDERPATH_GL11:
11554                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11555                                 {
11556                                         alpha = RSurf_FogVertex(v3f);
11557                                         c4f[0] *= alpha;
11558                                         c4f[1] *= alpha;
11559                                         c4f[2] *= alpha;
11560                                 }
11561                                 break;
11562                         }
11563                 }
11564
11565                 // now render the decals all at once
11566                 // (this assumes they all use one particle font texture!)
11567                 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);
11568                 R_Mesh_ResetTextureState();
11569                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11570                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11571                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11572                 GL_DepthMask(false);
11573                 GL_DepthRange(0, 1);
11574                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11575                 GL_DepthTest(true);
11576                 GL_CullFace(GL_NONE);
11577                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11578                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11579                 GL_LockArrays(0, numtris * 3);
11580                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11581                 GL_LockArrays(0, 0);
11582         }
11583 }
11584
11585 static void R_DrawModelDecals(void)
11586 {
11587         int i, numdecals;
11588
11589         // fade faster when there are too many decals
11590         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11591         for (i = 0;i < r_refdef.scene.numentities;i++)
11592                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11593
11594         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11595         for (i = 0;i < r_refdef.scene.numentities;i++)
11596                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11597                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11598
11599         R_DecalSystem_ApplySplatEntitiesQueue();
11600
11601         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11602         for (i = 0;i < r_refdef.scene.numentities;i++)
11603                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11604
11605         r_refdef.stats.totaldecals += numdecals;
11606
11607         if (r_showsurfaces.integer)
11608                 return;
11609
11610         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11611
11612         for (i = 0;i < r_refdef.scene.numentities;i++)
11613         {
11614                 if (!r_refdef.viewcache.entityvisible[i])
11615                         continue;
11616                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11617                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11618         }
11619 }
11620
11621 void R_DrawDebugModel(void)
11622 {
11623         entity_render_t *ent = rsurface.entity;
11624         int i, j, k, l, flagsmask;
11625         const int *elements;
11626         q3mbrush_t *brush;
11627         const msurface_t *surface;
11628         dp_model_t *model = ent->model;
11629         vec3_t v;
11630
11631         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11632
11633         R_Mesh_ColorPointer(NULL, 0, 0);
11634         R_Mesh_ResetTextureState();
11635         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11636         GL_DepthRange(0, 1);
11637         GL_DepthTest(!r_showdisabledepthtest.integer);
11638         GL_DepthMask(false);
11639         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11640
11641         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11642         {
11643                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11644                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11645                 {
11646                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11647                         {
11648                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11649                                 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);
11650                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11651                         }
11652                 }
11653                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11654                 {
11655                         if (surface->num_collisiontriangles)
11656                         {
11657                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11658                                 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);
11659                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11660                         }
11661                 }
11662         }
11663
11664         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11665
11666         if (r_showtris.integer || r_shownormals.integer)
11667         {
11668                 if (r_showdisabledepthtest.integer)
11669                 {
11670                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11671                         GL_DepthMask(false);
11672                 }
11673                 else
11674                 {
11675                         GL_BlendFunc(GL_ONE, GL_ZERO);
11676                         GL_DepthMask(true);
11677                 }
11678                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11679                 {
11680                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11681                                 continue;
11682                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11683                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11684                         {
11685                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11686                                 if (r_showtris.value > 0)
11687                                 {
11688                                         if (!rsurface.texture->currentlayers->depthmask)
11689                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11690                                         else if (ent == r_refdef.scene.worldentity)
11691                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11692                                         else
11693                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11694                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11695                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11696                                         R_Mesh_ColorPointer(NULL, 0, 0);
11697                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11698                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11699                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11700                                         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);
11701                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11702                                         CHECKGLERROR
11703                                 }
11704                                 if (r_shownormals.value < 0)
11705                                 {
11706                                         qglBegin(GL_LINES);
11707                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11708                                         {
11709                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11710                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11711                                                 qglVertex3f(v[0], v[1], v[2]);
11712                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11713                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11714                                                 qglVertex3f(v[0], v[1], v[2]);
11715                                         }
11716                                         qglEnd();
11717                                         CHECKGLERROR
11718                                 }
11719                                 if (r_shownormals.value > 0)
11720                                 {
11721                                         qglBegin(GL_LINES);
11722                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11723                                         {
11724                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11725                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11726                                                 qglVertex3f(v[0], v[1], v[2]);
11727                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11728                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11729                                                 qglVertex3f(v[0], v[1], v[2]);
11730                                         }
11731                                         qglEnd();
11732                                         CHECKGLERROR
11733                                         qglBegin(GL_LINES);
11734                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11735                                         {
11736                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11737                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11738                                                 qglVertex3f(v[0], v[1], v[2]);
11739                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11740                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11741                                                 qglVertex3f(v[0], v[1], v[2]);
11742                                         }
11743                                         qglEnd();
11744                                         CHECKGLERROR
11745                                         qglBegin(GL_LINES);
11746                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11747                                         {
11748                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11749                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11750                                                 qglVertex3f(v[0], v[1], v[2]);
11751                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11752                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11753                                                 qglVertex3f(v[0], v[1], v[2]);
11754                                         }
11755                                         qglEnd();
11756                                         CHECKGLERROR
11757                                 }
11758                         }
11759                 }
11760                 rsurface.texture = NULL;
11761         }
11762 }
11763
11764 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11765 int r_maxsurfacelist = 0;
11766 const msurface_t **r_surfacelist = NULL;
11767 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11768 {
11769         int i, j, endj, f, flagsmask;
11770         texture_t *t;
11771         dp_model_t *model = r_refdef.scene.worldmodel;
11772         msurface_t *surfaces;
11773         unsigned char *update;
11774         int numsurfacelist = 0;
11775         if (model == NULL)
11776                 return;
11777
11778         if (r_maxsurfacelist < model->num_surfaces)
11779         {
11780                 r_maxsurfacelist = model->num_surfaces;
11781                 if (r_surfacelist)
11782                         Mem_Free((msurface_t**)r_surfacelist);
11783                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11784         }
11785
11786         RSurf_ActiveWorldEntity();
11787
11788         surfaces = model->data_surfaces;
11789         update = model->brushq1.lightmapupdateflags;
11790
11791         // update light styles on this submodel
11792         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11793         {
11794                 model_brush_lightstyleinfo_t *style;
11795                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11796                 {
11797                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11798                         {
11799                                 int *list = style->surfacelist;
11800                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11801                                 for (j = 0;j < style->numsurfaces;j++)
11802                                         update[list[j]] = true;
11803                         }
11804                 }
11805         }
11806
11807         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11808
11809         if (debug)
11810         {
11811                 R_DrawDebugModel();
11812                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11813                 return;
11814         }
11815
11816         f = 0;
11817         t = NULL;
11818         rsurface.uselightmaptexture = false;
11819         rsurface.texture = NULL;
11820         rsurface.rtlight = NULL;
11821         numsurfacelist = 0;
11822         // add visible surfaces to draw list
11823         for (i = 0;i < model->nummodelsurfaces;i++)
11824         {
11825                 j = model->sortedmodelsurfaces[i];
11826                 if (r_refdef.viewcache.world_surfacevisible[j])
11827                         r_surfacelist[numsurfacelist++] = surfaces + j;
11828         }
11829         // update lightmaps if needed
11830         if (model->brushq1.firstrender)
11831         {
11832                 model->brushq1.firstrender = false;
11833                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11834                         if (update[j])
11835                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11836         }
11837         else if (update)
11838         {
11839                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11840                         if (r_refdef.viewcache.world_surfacevisible[j])
11841                                 if (update[j])
11842                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11843         }
11844         // don't do anything if there were no surfaces
11845         if (!numsurfacelist)
11846         {
11847                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11848                 return;
11849         }
11850         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11851         GL_AlphaTest(false);
11852
11853         // add to stats if desired
11854         if (r_speeds.integer && !skysurfaces && !depthonly)
11855         {
11856                 r_refdef.stats.world_surfaces += numsurfacelist;
11857                 for (j = 0;j < numsurfacelist;j++)
11858                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11859         }
11860
11861         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11862 }
11863
11864 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11865 {
11866         int i, j, endj, f, flagsmask;
11867         texture_t *t;
11868         dp_model_t *model = ent->model;
11869         msurface_t *surfaces;
11870         unsigned char *update;
11871         int numsurfacelist = 0;
11872         if (model == NULL)
11873                 return;
11874
11875         if (r_maxsurfacelist < model->num_surfaces)
11876         {
11877                 r_maxsurfacelist = model->num_surfaces;
11878                 if (r_surfacelist)
11879                         Mem_Free((msurface_t **)r_surfacelist);
11880                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11881         }
11882
11883         // if the model is static it doesn't matter what value we give for
11884         // wantnormals and wanttangents, so this logic uses only rules applicable
11885         // to a model, knowing that they are meaningless otherwise
11886         if (ent == r_refdef.scene.worldentity)
11887                 RSurf_ActiveWorldEntity();
11888         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11889                 RSurf_ActiveModelEntity(ent, false, false, false);
11890         else if (prepass)
11891                 RSurf_ActiveModelEntity(ent, true, true, true);
11892         else if (depthonly)
11893                 RSurf_ActiveModelEntity(ent, false, false, false);
11894         else
11895         {
11896                 switch (vid.renderpath)
11897                 {
11898                 case RENDERPATH_GL20:
11899                 case RENDERPATH_CGGL:
11900                         RSurf_ActiveModelEntity(ent, true, true, false);
11901                         break;
11902                 case RENDERPATH_GL13:
11903                 case RENDERPATH_GL11:
11904                         RSurf_ActiveModelEntity(ent, true, false, false);
11905                         break;
11906                 }
11907         }
11908
11909         surfaces = model->data_surfaces;
11910         update = model->brushq1.lightmapupdateflags;
11911
11912         // update light styles
11913         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11914         {
11915                 model_brush_lightstyleinfo_t *style;
11916                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11917                 {
11918                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11919                         {
11920                                 int *list = style->surfacelist;
11921                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11922                                 for (j = 0;j < style->numsurfaces;j++)
11923                                         update[list[j]] = true;
11924                         }
11925                 }
11926         }
11927
11928         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11929
11930         if (debug)
11931         {
11932                 R_DrawDebugModel();
11933                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11934                 return;
11935         }
11936
11937         f = 0;
11938         t = NULL;
11939         rsurface.uselightmaptexture = false;
11940         rsurface.texture = NULL;
11941         rsurface.rtlight = NULL;
11942         numsurfacelist = 0;
11943         // add visible surfaces to draw list
11944         for (i = 0;i < model->nummodelsurfaces;i++)
11945                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11946         // don't do anything if there were no surfaces
11947         if (!numsurfacelist)
11948         {
11949                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11950                 return;
11951         }
11952         // update lightmaps if needed
11953         if (update)
11954         {
11955                 int updated = 0;
11956                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11957                 {
11958                         if (update[j])
11959                         {
11960                                 updated++;
11961                                 R_BuildLightMap(ent, surfaces + j);
11962                         }
11963                 }
11964         }
11965         if (update)
11966                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11967                         if (update[j])
11968                                 R_BuildLightMap(ent, surfaces + j);
11969         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11970         GL_AlphaTest(false);
11971
11972         // add to stats if desired
11973         if (r_speeds.integer && !skysurfaces && !depthonly)
11974         {
11975                 r_refdef.stats.entities_surfaces += numsurfacelist;
11976                 for (j = 0;j < numsurfacelist;j++)
11977                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11978         }
11979
11980         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11981 }
11982
11983 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11984 {
11985         static texture_t texture;
11986         static msurface_t surface;
11987         const msurface_t *surfacelist = &surface;
11988
11989         // fake enough texture and surface state to render this geometry
11990
11991         texture.update_lastrenderframe = -1; // regenerate this texture
11992         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11993         texture.currentskinframe = skinframe;
11994         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11995         texture.specularscalemod = 1;
11996         texture.specularpowermod = 1;
11997
11998         surface.texture = &texture;
11999         surface.num_triangles = numtriangles;
12000         surface.num_firsttriangle = firsttriangle;
12001         surface.num_vertices = numvertices;
12002         surface.num_firstvertex = firstvertex;
12003
12004         // now render it
12005         rsurface.texture = R_GetCurrentTexture(surface.texture);
12006         rsurface.uselightmaptexture = false;
12007         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12008 }
12009
12010 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)
12011 {
12012         static msurface_t surface;
12013         const msurface_t *surfacelist = &surface;
12014
12015         // fake enough texture and surface state to render this geometry
12016
12017         surface.texture = texture;
12018         surface.num_triangles = numtriangles;
12019         surface.num_firsttriangle = firsttriangle;
12020         surface.num_vertices = numvertices;
12021         surface.num_firstvertex = firstvertex;
12022
12023         // now render it
12024         rsurface.texture = R_GetCurrentTexture(surface.texture);
12025         rsurface.uselightmaptexture = false;
12026         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12027 }