]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
this should work without strlen as well
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_frame = 0; ///< used only by R_GetCurrentTexture
33
34 qboolean r_loadnormalmap;
35 qboolean r_loadgloss;
36 qboolean r_loadfog;
37
38 //
39 // screen size info
40 //
41 r_refdef_t r_refdef;
42
43 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
44 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
45 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
46 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
47 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)"};
48 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
49 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
50 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
51
52 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
53 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"};
54 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
55 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)"};
56 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
57
58 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"};
59 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
60 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
61 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
62 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
63 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
64 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)"};
65 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
66 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
67 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"};
68 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"};
69 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
70 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"};
71 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"};
72 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"};
73 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
74 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
75 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
76 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
77 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)"};
78 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)"};
79 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
80 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
81 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
82 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
83 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
84 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
85 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
86 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."};
87 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
88 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
89 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
90 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."};
91 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
92 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
93 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"};
94 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"};
95 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
96 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
97 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
98 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
99 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"};
100
101 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
102 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
103 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
104 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
105 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
106 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
107 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
108 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
109
110 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
111 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
112 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
113
114 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)"};
115 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
116 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
117 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
118 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
119 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)"};
120 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)"};
121 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)"};
122 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)"};
123
124 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)"};
125 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
126 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"};
127 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
128 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
129
130 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
131 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
132 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
133 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
134
135 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
136 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
137 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
138 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
139 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
140 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
141 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
142
143 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
144 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
145 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
146 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)"};
147
148 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"};
149
150 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"};
151
152 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
153
154 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
155 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
156 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"};
157 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
158 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
159 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
160 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
161
162 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)"};
163
164 extern cvar_t v_glslgamma;
165
166 extern qboolean v_flipped_state;
167
168 static struct r_bloomstate_s
169 {
170         qboolean enabled;
171         qboolean hdr;
172
173         int bloomwidth, bloomheight;
174
175         int screentexturewidth, screentextureheight;
176         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
177
178         int bloomtexturewidth, bloomtextureheight;
179         rtexture_t *texture_bloom;
180
181         // arrays for rendering the screen passes
182         float screentexcoord2f[8];
183         float bloomtexcoord2f[8];
184         float offsettexcoord2f[8];
185
186         r_viewport_t viewport;
187 }
188 r_bloomstate;
189
190 r_waterstate_t r_waterstate;
191
192 /// shadow volume bsp struct with automatically growing nodes buffer
193 svbsp_t r_svbsp;
194
195 rtexture_t *r_texture_blanknormalmap;
196 rtexture_t *r_texture_white;
197 rtexture_t *r_texture_grey128;
198 rtexture_t *r_texture_black;
199 rtexture_t *r_texture_notexture;
200 rtexture_t *r_texture_whitecube;
201 rtexture_t *r_texture_normalizationcube;
202 rtexture_t *r_texture_fogattenuation;
203 rtexture_t *r_texture_gammaramps;
204 unsigned int r_texture_gammaramps_serial;
205 //rtexture_t *r_texture_fogintensity;
206
207 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
208 unsigned int r_numqueries;
209 unsigned int r_maxqueries;
210
211 typedef struct r_qwskincache_s
212 {
213         char name[MAX_QPATH];
214         skinframe_t *skinframe;
215 }
216 r_qwskincache_t;
217
218 static r_qwskincache_t *r_qwskincache;
219 static int r_qwskincache_size;
220
221 /// vertex coordinates for a quad that covers the screen exactly
222 const float r_screenvertex3f[12] =
223 {
224         0, 0, 0,
225         1, 0, 0,
226         1, 1, 0,
227         0, 1, 0
228 };
229
230 extern void R_DrawModelShadows(void);
231
232 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
233 {
234         int i;
235         for (i = 0;i < verts;i++)
236         {
237                 out[0] = in[0] * r;
238                 out[1] = in[1] * g;
239                 out[2] = in[2] * b;
240                 out[3] = in[3];
241                 in += 4;
242                 out += 4;
243         }
244 }
245
246 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
247 {
248         int i;
249         for (i = 0;i < verts;i++)
250         {
251                 out[0] = r;
252                 out[1] = g;
253                 out[2] = b;
254                 out[3] = a;
255                 out += 4;
256         }
257 }
258
259 // FIXME: move this to client?
260 void FOG_clear(void)
261 {
262         if (gamemode == GAME_NEHAHRA)
263         {
264                 Cvar_Set("gl_fogenable", "0");
265                 Cvar_Set("gl_fogdensity", "0.2");
266                 Cvar_Set("gl_fogred", "0.3");
267                 Cvar_Set("gl_foggreen", "0.3");
268                 Cvar_Set("gl_fogblue", "0.3");
269         }
270         r_refdef.fog_density = 0;
271         r_refdef.fog_red = 0;
272         r_refdef.fog_green = 0;
273         r_refdef.fog_blue = 0;
274         r_refdef.fog_alpha = 1;
275         r_refdef.fog_start = 0;
276         r_refdef.fog_end = 16384;
277         r_refdef.fog_height = 1<<30;
278         r_refdef.fog_fadedepth = 128;
279 }
280
281 static void R_BuildBlankTextures(void)
282 {
283         unsigned char data[4];
284         data[2] = 128; // normal X
285         data[1] = 128; // normal Y
286         data[0] = 255; // normal Z
287         data[3] = 128; // height
288         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
289         data[0] = 255;
290         data[1] = 255;
291         data[2] = 255;
292         data[3] = 255;
293         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
294         data[0] = 128;
295         data[1] = 128;
296         data[2] = 128;
297         data[3] = 255;
298         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
299         data[0] = 0;
300         data[1] = 0;
301         data[2] = 0;
302         data[3] = 255;
303         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
304 }
305
306 static void R_BuildNoTexture(void)
307 {
308         int x, y;
309         unsigned char pix[16][16][4];
310         // this makes a light grey/dark grey checkerboard texture
311         for (y = 0;y < 16;y++)
312         {
313                 for (x = 0;x < 16;x++)
314                 {
315                         if ((y < 8) ^ (x < 8))
316                         {
317                                 pix[y][x][0] = 128;
318                                 pix[y][x][1] = 128;
319                                 pix[y][x][2] = 128;
320                                 pix[y][x][3] = 255;
321                         }
322                         else
323                         {
324                                 pix[y][x][0] = 64;
325                                 pix[y][x][1] = 64;
326                                 pix[y][x][2] = 64;
327                                 pix[y][x][3] = 255;
328                         }
329                 }
330         }
331         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
332 }
333
334 static void R_BuildWhiteCube(void)
335 {
336         unsigned char data[6*1*1*4];
337         memset(data, 255, sizeof(data));
338         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
339 }
340
341 static void R_BuildNormalizationCube(void)
342 {
343         int x, y, side;
344         vec3_t v;
345         vec_t s, t, intensity;
346 #define NORMSIZE 64
347         unsigned char *data;
348         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
349         for (side = 0;side < 6;side++)
350         {
351                 for (y = 0;y < NORMSIZE;y++)
352                 {
353                         for (x = 0;x < NORMSIZE;x++)
354                         {
355                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
356                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
357                                 switch(side)
358                                 {
359                                 default:
360                                 case 0:
361                                         v[0] = 1;
362                                         v[1] = -t;
363                                         v[2] = -s;
364                                         break;
365                                 case 1:
366                                         v[0] = -1;
367                                         v[1] = -t;
368                                         v[2] = s;
369                                         break;
370                                 case 2:
371                                         v[0] = s;
372                                         v[1] = 1;
373                                         v[2] = t;
374                                         break;
375                                 case 3:
376                                         v[0] = s;
377                                         v[1] = -1;
378                                         v[2] = -t;
379                                         break;
380                                 case 4:
381                                         v[0] = s;
382                                         v[1] = -t;
383                                         v[2] = 1;
384                                         break;
385                                 case 5:
386                                         v[0] = -s;
387                                         v[1] = -t;
388                                         v[2] = -1;
389                                         break;
390                                 }
391                                 intensity = 127.0f / sqrt(DotProduct(v, v));
392                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
393                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
394                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
395                                 data[((side*64+y)*64+x)*4+3] = 255;
396                         }
397                 }
398         }
399         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
400         Mem_Free(data);
401 }
402
403 static void R_BuildFogTexture(void)
404 {
405         int x, b;
406 #define FOGWIDTH 256
407         unsigned char data1[FOGWIDTH][4];
408         //unsigned char data2[FOGWIDTH][4];
409         double d, r, alpha;
410
411         r_refdef.fogmasktable_start = r_refdef.fog_start;
412         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
413         r_refdef.fogmasktable_range = r_refdef.fogrange;
414         r_refdef.fogmasktable_density = r_refdef.fog_density;
415
416         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
417         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
418         {
419                 d = (x * r - r_refdef.fogmasktable_start);
420                 if(developer.integer >= 100)
421                         Con_Printf("%f ", d);
422                 d = max(0, d);
423                 if (r_fog_exp2.integer)
424                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
425                 else
426                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
427                 if(developer.integer >= 100)
428                         Con_Printf(" : %f ", alpha);
429                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
430                 if(developer.integer >= 100)
431                         Con_Printf(" = %f\n", alpha);
432                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
433         }
434
435         for (x = 0;x < FOGWIDTH;x++)
436         {
437                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
438                 data1[x][0] = b;
439                 data1[x][1] = b;
440                 data1[x][2] = b;
441                 data1[x][3] = 255;
442                 //data2[x][0] = 255 - b;
443                 //data2[x][1] = 255 - b;
444                 //data2[x][2] = 255 - b;
445                 //data2[x][3] = 255;
446         }
447         if (r_texture_fogattenuation)
448         {
449                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
450                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
451         }
452         else
453         {
454                 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);
455                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
456         }
457 }
458
459 static const char *builtinshaderstring =
460 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
461 "// written by Forest 'LordHavoc' Hale\n"
462 "\n"
463 "// enable various extensions depending on permutation:\n"
464 "\n"
465 "#ifdef VERTEX_SHADER\n"
466 "uniform mat4 ModelViewProjectionMatrix;\n"
467 "#endif\n"
468 "\n"
469 "#ifdef MODE_DEPTH_OR_SHADOW\n"
470 "#ifdef VERTEX_SHADER\n"
471 "void main(void)\n"
472 "{\n"
473 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
474 "}\n"
475 "#endif\n"
476 "#else // !MODE_DEPTH_ORSHADOW\n"
477 "#ifdef MODE_SHOWDEPTH\n"
478 "#ifdef VERTEX_SHADER\n"
479 "void main(void)\n"
480 "{\n"
481 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
482 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
483 "}\n"
484 "#endif\n"
485 "\n"
486 "#ifdef FRAGMENT_SHADER\n"
487 "void main(void)\n"
488 "{\n"
489 "       gl_FragColor = gl_Color;\n"
490 "}\n"
491 "#endif\n"
492 "#else // !MODE_SHOWDEPTH\n"
493 "#ifdef MODE_POSTPROCESS\n"
494 "varying vec2 TexCoord1;\n"
495 "varying vec2 TexCoord2;\n"
496 "\n"
497 "#ifdef VERTEX_SHADER\n"
498 "void main(void)\n"
499 "{\n"
500 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
501 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
502 "#ifdef USEBLOOM\n"
503 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
504 "#endif\n"
505 "}\n"
506 "#endif\n"
507 "\n"
508 "#ifdef FRAGMENT_SHADER\n"
509 "uniform sampler2D Texture_First;\n"
510 "#ifdef USEBLOOM\n"
511 "uniform sampler2D Texture_Second;\n"
512 "#endif\n"
513 "#ifdef USEGAMMARAMPS\n"
514 "uniform sampler2D Texture_GammaRamps;\n"
515 "#endif\n"
516 "#ifdef USESATURATION\n"
517 "uniform float Saturation;\n"
518 "#endif\n"
519 "#ifdef USEVIEWTINT\n"
520 "uniform vec4 ViewTintColor;\n"
521 "#endif\n"
522 "//uncomment these if you want to use them:\n"
523 "uniform vec4 UserVec1;\n"
524 "// uniform vec4 UserVec2;\n"
525 "// uniform vec4 UserVec3;\n"
526 "// uniform vec4 UserVec4;\n"
527 "// uniform float ClientTime;\n"
528 "uniform vec2 PixelSize;\n"
529 "void main(void)\n"
530 "{\n"
531 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
532 "#ifdef USEBLOOM\n"
533 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
534 "#endif\n"
535 "#ifdef USEVIEWTINT\n"
536 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
537 "#endif\n"
538 "\n"
539 "#ifdef USEPOSTPROCESSING\n"
540 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
541 "// 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"
542 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
543 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
544 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
545 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
546 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
547 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
548 "#endif\n"
549 "\n"
550 "#ifdef USESATURATION\n"
551 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
552 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
553 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
554 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
555 "#endif\n"
556 "\n"
557 "#ifdef USEGAMMARAMPS\n"
558 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
559 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
560 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
561 "#endif\n"
562 "}\n"
563 "#endif\n"
564 "#else // !MODE_POSTPROCESS\n"
565 "#ifdef MODE_GENERIC\n"
566 "#ifdef USEDIFFUSE\n"
567 "varying vec2 TexCoord1;\n"
568 "#endif\n"
569 "#ifdef USESPECULAR\n"
570 "varying vec2 TexCoord2;\n"
571 "#endif\n"
572 "#ifdef VERTEX_SHADER\n"
573 "void main(void)\n"
574 "{\n"
575 "       gl_FrontColor = gl_Color;\n"
576 "#ifdef USEDIFFUSE\n"
577 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
578 "#endif\n"
579 "#ifdef USESPECULAR\n"
580 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
581 "#endif\n"
582 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
583 "}\n"
584 "#endif\n"
585 "\n"
586 "#ifdef FRAGMENT_SHADER\n"
587 "#ifdef USEDIFFUSE\n"
588 "uniform sampler2D Texture_First;\n"
589 "#endif\n"
590 "#ifdef USESPECULAR\n"
591 "uniform sampler2D Texture_Second;\n"
592 "#endif\n"
593 "\n"
594 "void main(void)\n"
595 "{\n"
596 "       gl_FragColor = gl_Color;\n"
597 "#ifdef USEDIFFUSE\n"
598 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
599 "#endif\n"
600 "\n"
601 "#ifdef USESPECULAR\n"
602 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
603 "# ifdef USECOLORMAPPING\n"
604 "       gl_FragColor *= tex2;\n"
605 "# endif\n"
606 "# ifdef USEGLOW\n"
607 "       gl_FragColor += tex2;\n"
608 "# endif\n"
609 "# ifdef USEVERTEXTEXTUREBLEND\n"
610 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
611 "# endif\n"
612 "#endif\n"
613 "}\n"
614 "#endif\n"
615 "#else // !MODE_GENERIC\n"
616 "#ifdef MODE_BLOOMBLUR\n"
617 "varying TexCoord;\n"
618 "#ifdef VERTEX_SHADER\n"
619 "void main(void)\n"
620 "{\n"
621 "       gl_FrontColor = gl_Color;\n"
622 "       TexCoord = gl_MultiTexCoord0.xy;\n"
623 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
624 "}\n"
625 "#endif\n"
626 "\n"
627 "#ifdef FRAGMENT_SHADER\n"
628 "uniform sampler2D Texture_First;\n"
629 "uniform vec4 BloomBlur_Parameters;\n"
630 "\n"
631 "void main(void)\n"
632 "{\n"
633 "       int i;\n"
634 "       vec2 tc = TexCoord;\n"
635 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
636 "       tc += BloomBlur_Parameters.xy;\n"
637 "       for (i = 1;i < SAMPLES;i++)\n"
638 "       {\n"
639 "               color += texture2D(Texture_First, tc).rgb;\n"
640 "               tc += BloomBlur_Parameters.xy;\n"
641 "       }\n"
642 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
643 "}\n"
644 "#endif\n"
645 "#else // !MODE_BLOOMBLUR\n"
646 "#ifdef MODE_REFRACTION\n"
647 "varying vec2 TexCoord;\n"
648 "varying vec4 ModelViewProjectionPosition;\n"
649 "uniform mat4 TexMatrix;\n"
650 "#ifdef VERTEX_SHADER\n"
651 "\n"
652 "void main(void)\n"
653 "{\n"
654 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
655 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
656 "       ModelViewProjectionPosition = gl_Position;\n"
657 "}\n"
658 "#endif\n"
659 "\n"
660 "#ifdef FRAGMENT_SHADER\n"
661 "uniform sampler2D Texture_Normal;\n"
662 "uniform sampler2D Texture_Refraction;\n"
663 "uniform sampler2D Texture_Reflection;\n"
664 "\n"
665 "uniform vec4 DistortScaleRefractReflect;\n"
666 "uniform vec4 ScreenScaleRefractReflect;\n"
667 "uniform vec4 ScreenCenterRefractReflect;\n"
668 "uniform vec4 RefractColor;\n"
669 "uniform vec4 ReflectColor;\n"
670 "uniform float ReflectFactor;\n"
671 "uniform float ReflectOffset;\n"
672 "\n"
673 "void main(void)\n"
674 "{\n"
675 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
676 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
677 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
678 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
679 "       // FIXME temporary hack to detect the case that the reflection\n"
680 "       // gets blackened at edges due to leaving the area that contains actual\n"
681 "       // content.\n"
682 "       // Remove this 'ack once we have a better way to stop this thing from\n"
683 "       // 'appening.\n"
684 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
685 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
686 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
687 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
688 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
689 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
690 "}\n"
691 "#endif\n"
692 "#else // !MODE_REFRACTION\n"
693 "#ifdef MODE_WATER\n"
694 "varying vec2 TexCoord;\n"
695 "varying vec3 EyeVector;\n"
696 "varying vec4 ModelViewProjectionPosition;\n"
697 "#ifdef VERTEX_SHADER\n"
698 "uniform vec3 EyePosition;\n"
699 "uniform mat4 TexMatrix;\n"
700 "\n"
701 "void main(void)\n"
702 "{\n"
703 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
704 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
705 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
706 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
707 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
708 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
709 "       ModelViewProjectionPosition = gl_Position;\n"
710 "}\n"
711 "#endif\n"
712 "\n"
713 "#ifdef FRAGMENT_SHADER\n"
714 "uniform sampler2D Texture_Normal;\n"
715 "uniform sampler2D Texture_Refraction;\n"
716 "uniform sampler2D Texture_Reflection;\n"
717 "\n"
718 "uniform vec4 DistortScaleRefractReflect;\n"
719 "uniform vec4 ScreenScaleRefractReflect;\n"
720 "uniform vec4 ScreenCenterRefractReflect;\n"
721 "uniform vec4 RefractColor;\n"
722 "uniform vec4 ReflectColor;\n"
723 "uniform float ReflectFactor;\n"
724 "uniform float ReflectOffset;\n"
725 "\n"
726 "void main(void)\n"
727 "{\n"
728 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
729 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
730 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
731 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
732 "       // FIXME temporary hack to detect the case that the reflection\n"
733 "       // gets blackened at edges due to leaving the area that contains actual\n"
734 "       // content.\n"
735 "       // Remove this 'ack once we have a better way to stop this thing from\n"
736 "       // 'appening.\n"
737 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
738 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
739 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
740 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
741 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
742 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
743 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
744 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
745 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
746 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
747 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
748 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
749 "}\n"
750 "#endif\n"
751 "#else // !MODE_WATER\n"
752 "\n"
753 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
754 "# extension GL_ARB_texture_rectangle : enable\n"
755 "#endif\n"
756 "\n"
757 "#ifdef USESHADOWMAP2D\n"
758 "# ifdef GL_EXT_gpu_shader4\n"
759 "#   extension GL_EXT_gpu_shader4 : enable\n"
760 "# endif\n"
761 "# ifdef GL_ARB_texture_gather\n"
762 "#   extension GL_ARB_texture_gather : enable\n"
763 "# else\n"
764 "#   ifdef GL_AMD_texture_texture4\n"
765 "#     extension GL_AMD_texture_texture4 : enable\n"
766 "#   endif\n"
767 "# endif\n"
768 "#endif\n"
769 "\n"
770 "#ifdef USESHADOWMAPCUBE\n"
771 "# extension GL_EXT_gpu_shader4 : enable\n"
772 "#endif\n"
773 "\n"
774 "#ifdef USESHADOWSAMPLER\n"
775 "# extension GL_ARB_shadow : enable\n"
776 "#endif\n"
777 "\n"
778 "// common definitions between vertex shader and fragment shader:\n"
779 "\n"
780 "//#ifdef __GLSL_CG_DATA_TYPES\n"
781 "//# define myhalf half\n"
782 "//# define myhalf2 half2\n"
783 "//# define myhalf3half3\n"
784 "//# define myhalf4 half4\n"
785 "//#else\n"
786 "# define myhalf float\n"
787 "# define myhalf2 vec2\n"
788 "# define myhalf3 vec3\n"
789 "# define myhalf4 vec4\n"
790 "//#endif\n"
791 "\n"
792 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
793 "# define USEFOG\n"
794 "#endif\n"
795 "\n"
796 "varying vec2 TexCoord;\n"
797 "#ifdef USEVERTEXTEXTUREBLEND\n"
798 "varying vec2 TexCoord2;\n"
799 "#endif\n"
800 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
801 "#define USELIGHTMAP\n"
802 "varying vec2 TexCoordLightmap;\n"
803 "#endif\n"
804 "\n"
805 "#ifdef MODE_LIGHTSOURCE\n"
806 "varying vec3 CubeVector;\n"
807 "#endif\n"
808 "\n"
809 "#ifdef MODE_LIGHTSOURCE\n"
810 "varying vec3 LightVector;\n"
811 "#endif\n"
812 "#if defined(MODE_LIGHTDIRECTION)\n"
813 "varying vec3 LightVector;\n"
814 "#endif\n"
815 "\n"
816 "#if defined(USEOFFSETMAPPING) || defined(USESPECULAR)\n"
817 "//#if defined(USEOFFSETMAPPING) || defined(USESPECULAR) || defined(MODE_LIGHTDIRECTION) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
818 "#define USEEYEVECTOR\n"
819 "varying vec3 EyeVector;\n"
820 "#endif\n"
821 "#ifdef USEFOG\n"
822 "varying vec3 EyeVectorModelSpace;\n"
823 "varying float FogPlaneVertexDist;\n"
824 "#endif\n"
825 "\n"
826 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
827 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
828 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
829 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
830 "#endif\n"
831 "\n"
832 "#ifdef USEREFLECTION\n"
833 "varying vec4 ModelViewProjectionPosition;\n"
834 "#endif\n"
835 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
836 "uniform vec3 LightPosition;\n"
837 "varying vec4 ModelViewPosition;\n"
838 "#endif\n"
839 "\n"
840 "#ifdef MODE_LIGHTSOURCE\n"
841 "uniform vec3 LightPosition;\n"
842 "#endif\n"
843 "uniform vec3 EyePosition;\n"
844 "#ifdef MODE_LIGHTDIRECTION\n"
845 "uniform vec3 LightDir;\n"
846 "#endif\n"
847 "uniform vec4 FogPlane;\n"
848 "\n"
849 "\n"
850 "\n"
851 "\n"
852 "\n"
853 "// vertex shader specific:\n"
854 "#ifdef VERTEX_SHADER\n"
855 "\n"
856 "// 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"
857 "\n"
858 "#ifdef MODE_DEFERREDGEOMETRY\n"
859 "uniform mat4 TexMatrix;\n"
860 "#ifdef USEVERTEXTEXTUREBLEND\n"
861 "uniform mat4 BackgroundTexMatrix;\n"
862 "#endif\n"
863 "uniform mat4 ModelViewMatrix;\n"
864 "void main(void)\n"
865 "{\n"
866 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
867 "#ifdef USEVERTEXTEXTUREBLEND\n"
868 "       gl_FrontColor = gl_Color;\n"
869 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
870 "#endif\n"
871 "\n"
872 "       // transform unnormalized eye direction into tangent space\n"
873 "#ifdef USEOFFSETMAPPING\n"
874 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
875 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
876 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
877 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
878 "#endif\n"
879 "\n"
880 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
881 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
882 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
883 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
884 "}\n"
885 "#else // !MODE_DEFERREDGEOMETRY\n"
886 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
887 "uniform mat4 ModelViewMatrix;\n"
888 "void main(void)\n"
889 "{\n"
890 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
891 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
892 "}\n"
893 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
894 "uniform mat4 TexMatrix;\n"
895 "#ifdef USEVERTEXTEXTUREBLEND\n"
896 "uniform mat4 BackgroundTexMatrix;\n"
897 "#endif\n"
898 "#ifdef MODE_LIGHTSOURCE\n"
899 "uniform mat4 ModelToLight;\n"
900 "#endif\n"
901 "void main(void)\n"
902 "{\n"
903 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
904 "       gl_FrontColor = gl_Color;\n"
905 "#endif\n"
906 "       // copy the surface texcoord\n"
907 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
908 "#ifdef USEVERTEXTEXTUREBLEND\n"
909 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
910 "#endif\n"
911 "#ifdef USELIGHTMAP\n"
912 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
913 "#endif\n"
914 "\n"
915 "#ifdef MODE_LIGHTSOURCE\n"
916 "       // transform vertex position into light attenuation/cubemap space\n"
917 "       // (-1 to +1 across the light box)\n"
918 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
919 "\n"
920 "# ifdef USEDIFFUSE\n"
921 "       // transform unnormalized light direction into tangent space\n"
922 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
923 "       //  normalize it per pixel)\n"
924 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
925 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
926 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
927 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
928 "# endif\n"
929 "#endif\n"
930 "\n"
931 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
932 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
933 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
934 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
935 "#endif\n"
936 "\n"
937 "       // transform unnormalized eye direction into tangent space\n"
938 "#ifdef USEEYEVECTOR\n"
939 "#ifndef USEFOG\n"
940 "       vec3 EyeVectorModelSpace;\n"
941 "#endif\n"
942 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
943 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
944 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
945 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
946 "#endif\n"
947 "\n"
948 "#ifdef USEFOG\n"
949 "#ifndef USEEYEVECTOR\n"
950 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
951 "#endif\n"
952 "       FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
953 "#endif\n"
954 "\n"
955 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
956 "       VectorS = gl_MultiTexCoord1.xyz;\n"
957 "       VectorT = gl_MultiTexCoord2.xyz;\n"
958 "       VectorR = gl_MultiTexCoord3.xyz;\n"
959 "#endif\n"
960 "\n"
961 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
962 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
963 "\n"
964 "#ifdef USEREFLECTION\n"
965 "       ModelViewProjectionPosition = gl_Position;\n"
966 "#endif\n"
967 "}\n"
968 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
969 "#endif // !MODE_DEFERREDGEOMETRY\n"
970 "\n"
971 "#endif // VERTEX_SHADER\n"
972 "\n"
973 "\n"
974 "\n"
975 "\n"
976 "// fragment shader specific:\n"
977 "#ifdef FRAGMENT_SHADER\n"
978 "\n"
979 "uniform sampler2D Texture_Normal;\n"
980 "uniform sampler2D Texture_Color;\n"
981 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
982 "uniform sampler2D Texture_Gloss;\n"
983 "//#endif\n"
984 "#ifdef USEGLOW\n"
985 "uniform sampler2D Texture_Glow;\n"
986 "#endif\n"
987 "#ifdef USEVERTEXTEXTUREBLEND\n"
988 "uniform sampler2D Texture_SecondaryNormal;\n"
989 "uniform sampler2D Texture_SecondaryColor;\n"
990 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
991 "uniform sampler2D Texture_SecondaryGloss;\n"
992 "//#endif\n"
993 "#ifdef USEGLOW\n"
994 "uniform sampler2D Texture_SecondaryGlow;\n"
995 "#endif\n"
996 "#endif\n"
997 "#ifdef USECOLORMAPPING\n"
998 "uniform sampler2D Texture_Pants;\n"
999 "uniform sampler2D Texture_Shirt;\n"
1000 "#endif\n"
1001 "#ifdef USEFOG\n"
1002 "uniform sampler2D Texture_FogMask;\n"
1003 "#endif\n"
1004 "#ifdef USELIGHTMAP\n"
1005 "uniform sampler2D Texture_Lightmap;\n"
1006 "#endif\n"
1007 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1008 "uniform sampler2D Texture_Deluxemap;\n"
1009 "#endif\n"
1010 "#ifdef USEREFLECTION\n"
1011 "uniform sampler2D Texture_Reflection;\n"
1012 "#endif\n"
1013 "\n"
1014 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1015 "uniform sampler2DRect Texture_ScreenDepth;\n"
1016 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
1017 "#endif\n"
1018 "#ifdef USEDEFERREDLIGHTMAP\n"
1019 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
1020 "uniform sampler2DRect Texture_ScreenSpecular;\n"
1021 "#endif\n"
1022 "\n"
1023 "uniform myhalf3 Color_Pants;\n"
1024 "uniform myhalf3 Color_Shirt;\n"
1025 "uniform myhalf3 FogColor;\n"
1026 "\n"
1027 "#ifdef USEFOG\n"
1028 "uniform float FogRangeRecip;\n"
1029 "uniform float FogPlaneViewDist;\n"
1030 "uniform float FogHeightFade;\n"
1031 "myhalf FogVertex(void)\n"
1032 "{\n"
1033 "       float fogfrac;\n"
1034 "#ifdef USEFOGOUTSIDE\n"
1035 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1036 "#else\n"
1037 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1038 "#endif\n"
1039 "       return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1040 "}\n"
1041 "#endif\n"
1042 "\n"
1043 "#ifdef USEOFFSETMAPPING\n"
1044 "uniform float OffsetMapping_Scale;\n"
1045 "vec2 OffsetMapping(vec2 TexCoord)\n"
1046 "{\n"
1047 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1048 "       // 14 sample relief mapping: linear search and then binary search\n"
1049 "       // this basically steps forward a small amount repeatedly until it finds\n"
1050 "       // itself inside solid, then jitters forward and back using decreasing\n"
1051 "       // amounts to find the impact\n"
1052 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1053 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1054 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1055 "       vec3 RT = vec3(TexCoord, 1);\n"
1056 "       OffsetVector *= 0.1;\n"
1057 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1058 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1059 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1060 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1061 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1062 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1063 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1064 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1065 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1066 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1067 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1068 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1069 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1070 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1071 "       return RT.xy;\n"
1072 "#else\n"
1073 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1074 "       // this basically moves forward the full distance, and then backs up based\n"
1075 "       // on height of samples\n"
1076 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1077 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1078 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1079 "       TexCoord += OffsetVector;\n"
1080 "       OffsetVector *= 0.333;\n"
1081 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1082 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1083 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1084 "       return TexCoord;\n"
1085 "#endif\n"
1086 "}\n"
1087 "#endif // USEOFFSETMAPPING\n"
1088 "\n"
1089 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1090 "uniform sampler2D Texture_Attenuation;\n"
1091 "uniform samplerCube Texture_Cube;\n"
1092 "\n"
1093 "#ifdef USESHADOWMAPRECT\n"
1094 "# ifdef USESHADOWSAMPLER\n"
1095 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1096 "# else\n"
1097 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1098 "# endif\n"
1099 "#endif\n"
1100 "\n"
1101 "#ifdef USESHADOWMAP2D\n"
1102 "# ifdef USESHADOWSAMPLER\n"
1103 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1104 "# else\n"
1105 "uniform sampler2D Texture_ShadowMap2D;\n"
1106 "# endif\n"
1107 "#endif\n"
1108 "\n"
1109 "#ifdef USESHADOWMAPVSDCT\n"
1110 "uniform samplerCube Texture_CubeProjection;\n"
1111 "#endif\n"
1112 "\n"
1113 "#ifdef USESHADOWMAPCUBE\n"
1114 "# ifdef USESHADOWSAMPLER\n"
1115 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1116 "# else\n"
1117 "uniform samplerCube Texture_ShadowMapCube;\n"
1118 "# endif\n"
1119 "#endif\n"
1120 "\n"
1121 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1122 "uniform vec2 ShadowMap_TextureScale;\n"
1123 "uniform vec4 ShadowMap_Parameters;\n"
1124 "#endif\n"
1125 "\n"
1126 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1127 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1128 "{\n"
1129 "       vec3 adir = abs(dir);\n"
1130 "# ifndef USESHADOWMAPVSDCT\n"
1131 "       vec2 tc;\n"
1132 "       vec2 offset;\n"
1133 "       float ma;\n"
1134 "       if (adir.x > adir.y)\n"
1135 "       {\n"
1136 "               if (adir.x > adir.z) // X\n"
1137 "               {\n"
1138 "                       ma = adir.x;\n"
1139 "                       tc = dir.zy;\n"
1140 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1141 "               }\n"
1142 "               else // Z\n"
1143 "               {\n"
1144 "                       ma = adir.z;\n"
1145 "                       tc = dir.xy;\n"
1146 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1147 "               }\n"
1148 "       }\n"
1149 "       else\n"
1150 "       {\n"
1151 "               if (adir.y > adir.z) // Y\n"
1152 "               {\n"
1153 "                       ma = adir.y;\n"
1154 "                       tc = dir.xz;\n"
1155 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1156 "               }\n"
1157 "               else // Z\n"
1158 "               {\n"
1159 "                       ma = adir.z;\n"
1160 "                       tc = dir.xy;\n"
1161 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1162 "               }\n"
1163 "       }\n"
1164 "\n"
1165 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1166 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1167 "       stc.z += ShadowMap_Parameters.z;\n"
1168 "       return stc;\n"
1169 "# else\n"
1170 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1171 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1172 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1173 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1174 "       stc.z += ShadowMap_Parameters.z;\n"
1175 "       return stc;\n"
1176 "# endif\n"
1177 "}\n"
1178 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1179 "\n"
1180 "#ifdef USESHADOWMAPCUBE\n"
1181 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1182 "{\n"
1183 "    vec3 adir = abs(dir);\n"
1184 "    return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1185 "}\n"
1186 "#endif\n"
1187 "\n"
1188 "# ifdef USESHADOWMAPRECT\n"
1189 "float ShadowMapCompare(vec3 dir)\n"
1190 "{\n"
1191 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1192 "       float f;\n"
1193 "#  ifdef USESHADOWSAMPLER\n"
1194 "\n"
1195 "#    ifdef USESHADOWMAPPCF\n"
1196 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1197 "    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"
1198 "#    else\n"
1199 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1200 "#    endif\n"
1201 "\n"
1202 "#  else\n"
1203 "\n"
1204 "#    ifdef USESHADOWMAPPCF\n"
1205 "#      if USESHADOWMAPPCF > 1\n"
1206 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1207 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1208 "    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"
1209 "    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"
1210 "    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"
1211 "    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"
1212 "    vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1213 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1214 "#      else\n"
1215 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1216 "    vec2 offset = fract(shadowmaptc.xy);\n"
1217 "    vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1218 "    vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1219 "    vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1220 "    vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1221 "    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1222 "#      endif\n"
1223 "#    else\n"
1224 "    f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1225 "#    endif\n"
1226 "\n"
1227 "#  endif\n"
1228 "       return f;\n"
1229 "}\n"
1230 "# endif\n"
1231 "\n"
1232 "# ifdef USESHADOWMAP2D\n"
1233 "float ShadowMapCompare(vec3 dir)\n"
1234 "{\n"
1235 "    vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1236 "    float f;\n"
1237 "\n"
1238 "#  ifdef USESHADOWSAMPLER\n"
1239 "#    ifdef USESHADOWMAPPCF\n"
1240 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1241 "    vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1242 "    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"
1243 "#    else\n"
1244 "    f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1245 "#    endif\n"
1246 "#  else\n"
1247 "#    ifdef USESHADOWMAPPCF\n"
1248 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1249 "#      ifdef GL_ARB_texture_gather\n"
1250 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1251 "#      else\n"
1252 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1253 "#      endif\n"
1254 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1255 "    center *= ShadowMap_TextureScale;\n"
1256 "    vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1257 "    vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1258 "    vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1259 "    vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1260 "    vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1261 "                mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1262 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1263 "#     else\n"
1264 "#      ifdef GL_EXT_gpu_shader4\n"
1265 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1266 "#      else\n"
1267 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1268 "#      endif\n"
1269 "#      if USESHADOWMAPPCF > 1\n"
1270 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1271 "    center *= ShadowMap_TextureScale;\n"
1272 "    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"
1273 "    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"
1274 "    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"
1275 "    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"
1276 "    vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1277 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1278 "#      else\n"
1279 "    vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1280 "    vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1281 "    vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1282 "    vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1283 "    vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1284 "    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1285 "#      endif\n"
1286 "#     endif\n"
1287 "#    else\n"
1288 "    f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1289 "#    endif\n"
1290 "#  endif\n"
1291 "    return f;\n"
1292 "}\n"
1293 "# endif\n"
1294 "\n"
1295 "# ifdef USESHADOWMAPCUBE\n"
1296 "float ShadowMapCompare(vec3 dir)\n"
1297 "{\n"
1298 "    // apply depth texture cubemap as light filter\n"
1299 "    vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1300 "    float f;\n"
1301 "#  ifdef USESHADOWSAMPLER\n"
1302 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1303 "#  else\n"
1304 "    f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1305 "#  endif\n"
1306 "    return f;\n"
1307 "}\n"
1308 "# endif\n"
1309 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1310 "\n"
1311 "#ifdef MODE_DEFERREDGEOMETRY\n"
1312 "void main(void)\n"
1313 "{\n"
1314 "#ifdef USEOFFSETMAPPING\n"
1315 "       // apply offsetmapping\n"
1316 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1317 "#define TexCoord TexCoordOffset\n"
1318 "#endif\n"
1319 "\n"
1320 "#ifdef USEALPHAKILL\n"
1321 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1322 "               discard;\n"
1323 "#endif\n"
1324 "\n"
1325 "#ifdef USEVERTEXTEXTUREBLEND\n"
1326 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1327 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1328 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1329 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1330 "#endif\n"
1331 "\n"
1332 "#ifdef USEVERTEXTEXTUREBLEND\n"
1333 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1334 "#else\n"
1335 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1336 "#endif\n"
1337 "\n"
1338 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1339 "}\n"
1340 "#else // !MODE_DEFERREDGEOMETRY\n"
1341 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1342 "uniform mat4 ViewToLight;\n"
1343 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1344 "uniform vec2 ScreenToDepth;\n"
1345 "uniform myhalf3 DeferredColor_Ambient;\n"
1346 "uniform myhalf3 DeferredColor_Diffuse;\n"
1347 "#ifdef USESPECULAR\n"
1348 "uniform myhalf3 DeferredColor_Specular;\n"
1349 "uniform myhalf SpecularPower;\n"
1350 "#endif\n"
1351 "void main(void)\n"
1352 "{\n"
1353 "       // calculate viewspace pixel position\n"
1354 "       vec3 position;\n"
1355 "       position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1356 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1357 "       // decode viewspace pixel normal\n"
1358 "       myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1359 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1360 "       // surfacenormal = pixel normal in viewspace\n"
1361 "       // LightVector = pixel to light in viewspace\n"
1362 "       // CubeVector = position in lightspace\n"
1363 "       // eyevector = pixel to view in viewspace\n"
1364 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1365 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1366 "#ifdef USEDIFFUSE\n"
1367 "       // calculate diffuse shading\n"
1368 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1369 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1370 "#endif\n"
1371 "#ifdef USESPECULAR\n"
1372 "       // calculate directional shading\n"
1373 "       vec3 eyevector = position * -1.0;\n"
1374 "#  ifdef USEEXACTSPECULARMATH\n"
1375 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1376 "#  else\n"
1377 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1378 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1379 "#  endif\n"
1380 "#endif\n"
1381 "\n"
1382 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1383 "       fade *= ShadowMapCompare(CubeVector);\n"
1384 "#endif\n"
1385 "\n"
1386 "#ifdef USEDIFFUSE\n"
1387 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1388 "#else\n"
1389 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1390 "#endif\n"
1391 "#ifdef USESPECULAR\n"
1392 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1393 "#else\n"
1394 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1395 "#endif\n"
1396 "\n"
1397 "# ifdef USECUBEFILTER\n"
1398 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1399 "       gl_FragData[0] *= cubecolor;\n"
1400 "       gl_FragData[1] *= cubecolor;\n"
1401 "# endif\n"
1402 "}\n"
1403 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1404 "#ifdef USEDEFERREDLIGHTMAP\n"
1405 "uniform myhalf3 DeferredMod_Diffuse;\n"
1406 "uniform myhalf3 DeferredMod_Specular;\n"
1407 "#endif\n"
1408 "uniform myhalf3 Color_Ambient;\n"
1409 "uniform myhalf3 Color_Diffuse;\n"
1410 "uniform myhalf3 Color_Specular;\n"
1411 "uniform myhalf SpecularPower;\n"
1412 "#ifdef USEGLOW\n"
1413 "uniform myhalf3 Color_Glow;\n"
1414 "#endif\n"
1415 "uniform myhalf Alpha;\n"
1416 "#ifdef USEREFLECTION\n"
1417 "uniform vec4 DistortScaleRefractReflect;\n"
1418 "uniform vec4 ScreenScaleRefractReflect;\n"
1419 "uniform vec4 ScreenCenterRefractReflect;\n"
1420 "uniform myhalf4 ReflectColor;\n"
1421 "#endif\n"
1422 "#ifdef MODE_LIGHTDIRECTION\n"
1423 "uniform myhalf3 LightColor;\n"
1424 "#endif\n"
1425 "#ifdef MODE_LIGHTSOURCE\n"
1426 "uniform myhalf3 LightColor;\n"
1427 "#endif\n"
1428 "void main(void)\n"
1429 "{\n"
1430 "#ifdef USEOFFSETMAPPING\n"
1431 "       // apply offsetmapping\n"
1432 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1433 "#define TexCoord TexCoordOffset\n"
1434 "#endif\n"
1435 "\n"
1436 "       // combine the diffuse textures (base, pants, shirt)\n"
1437 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1438 "#ifdef USEALPHAKILL\n"
1439 "       if (color.a < 0.5)\n"
1440 "               discard;\n"
1441 "#endif\n"
1442 "       color.a *= Alpha;\n"
1443 "#ifdef USECOLORMAPPING\n"
1444 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1445 "#endif\n"
1446 "#ifdef USEVERTEXTEXTUREBLEND\n"
1447 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1448 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1449 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1450 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1451 "       color.a = 1.0;\n"
1452 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1453 "#endif\n"
1454 "\n"
1455 "       // get the surface normal\n"
1456 "#ifdef USEVERTEXTEXTUREBLEND\n"
1457 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1458 "#else\n"
1459 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1460 "#endif\n"
1461 "\n"
1462 "       // get the material colors\n"
1463 "       myhalf3 diffusetex = color.rgb;\n"
1464 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1465 "# ifdef USEVERTEXTEXTUREBLEND\n"
1466 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1467 "# else\n"
1468 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1469 "# endif\n"
1470 "#endif\n"
1471 "\n"
1472 "\n"
1473 "\n"
1474 "\n"
1475 "#ifdef MODE_LIGHTSOURCE\n"
1476 "       // light source\n"
1477 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1478 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1479 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1480 "#ifdef USESPECULAR\n"
1481 "#ifdef USEEXACTSPECULARMATH\n"
1482 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1483 "#else\n"
1484 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1485 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1486 "#endif\n"
1487 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1488 "#endif\n"
1489 "       color.rgb *= LightColor;\n"
1490 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1491 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1492 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1493 "#endif\n"
1494 "# ifdef USECUBEFILTER\n"
1495 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1496 "# endif\n"
1497 "#endif // MODE_LIGHTSOURCE\n"
1498 "\n"
1499 "\n"
1500 "\n"
1501 "\n"
1502 "#ifdef MODE_LIGHTDIRECTION\n"
1503 "#define SHADING\n"
1504 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1505 "#define lightcolor LightColor\n"
1506 "#endif // MODE_LIGHTDIRECTION\n"
1507 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1508 "#define SHADING\n"
1509 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1510 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1511 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1512 "       // convert modelspace light vector to tangentspace\n"
1513 "       myhalf3 lightnormal;\n"
1514 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1515 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1516 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1517 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1518 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1519 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1520 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1521 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1522 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1523 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1524 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1525 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1526 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1527 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1528 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1529 "#define SHADING\n"
1530 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1531 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1532 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1533 "#endif\n"
1534 "\n"
1535 "\n"
1536 "\n"
1537 "\n"
1538 "#ifdef MODE_LIGHTMAP\n"
1539 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1540 "#endif // MODE_LIGHTMAP\n"
1541 "#ifdef MODE_VERTEXCOLOR\n"
1542 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1543 "#endif // MODE_VERTEXCOLOR\n"
1544 "#ifdef MODE_FLATCOLOR\n"
1545 "       color.rgb = diffusetex * Color_Ambient;\n"
1546 "#endif // MODE_FLATCOLOR\n"
1547 "\n"
1548 "\n"
1549 "\n"
1550 "\n"
1551 "#ifdef SHADING\n"
1552 "# ifdef USEDIFFUSE\n"
1553 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1554 "#  ifdef USESPECULAR\n"
1555 "#   ifdef USEEXACTSPECULARMATH\n"
1556 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1557 "#   else\n"
1558 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1559 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1560 "#   endif\n"
1561 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1562 "#  else\n"
1563 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1564 "#  endif\n"
1565 "# else\n"
1566 "       color.rgb = diffusetex * Color_Ambient;\n"
1567 "# endif\n"
1568 "#endif\n"
1569 "\n"
1570 "#ifdef USEDEFERREDLIGHTMAP\n"
1571 "       color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1572 "       color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1573 "#endif\n"
1574 "\n"
1575 "#ifdef USEGLOW\n"
1576 "#ifdef USEVERTEXTEXTUREBLEND\n"
1577 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1578 "#else\n"
1579 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1580 "#endif\n"
1581 "#endif\n"
1582 "\n"
1583 "#ifdef USEFOG\n"
1584 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1585 "#endif\n"
1586 "\n"
1587 "       // 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"
1588 "#ifdef USEREFLECTION\n"
1589 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1590 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1591 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1592 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1593 "       // FIXME temporary hack to detect the case that the reflection\n"
1594 "       // gets blackened at edges due to leaving the area that contains actual\n"
1595 "       // content.\n"
1596 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1597 "       // 'appening.\n"
1598 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1599 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1600 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1601 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1602 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1603 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1604 "#endif\n"
1605 "\n"
1606 "       gl_FragColor = vec4(color);\n"
1607 "}\n"
1608 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1609 "#endif // !MODE_DEFERREDGEOMETRY\n"
1610 "\n"
1611 "#endif // FRAGMENT_SHADER\n"
1612 "\n"
1613 "#endif // !MODE_WATER\n"
1614 "#endif // !MODE_REFRACTION\n"
1615 "#endif // !MODE_BLOOMBLUR\n"
1616 "#endif // !MODE_GENERIC\n"
1617 "#endif // !MODE_POSTPROCESS\n"
1618 "#endif // !MODE_SHOWDEPTH\n"
1619 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1620 ;
1621
1622 const char *builtincgshaderstring = "";
1623
1624 typedef struct shaderpermutationinfo_s
1625 {
1626         const char *pretext;
1627         const char *name;
1628 }
1629 shaderpermutationinfo_t;
1630
1631 typedef struct shadermodeinfo_s
1632 {
1633         const char *vertexfilename;
1634         const char *geometryfilename;
1635         const char *fragmentfilename;
1636         const char *pretext;
1637         const char *name;
1638 }
1639 shadermodeinfo_t;
1640
1641 typedef enum shaderpermutation_e
1642 {
1643         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1644         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1645         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1646         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1647         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1648         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1649         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1650         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1651         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1652         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1653         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1654         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1655         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1656         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1657         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1658         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1659         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1660         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1661         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1662         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1663         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1664         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1665         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1666         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1667         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1668         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
1669         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
1670         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
1671 }
1672 shaderpermutation_t;
1673
1674 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1675 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1676 {
1677         {"#define USEDIFFUSE\n", " diffuse"},
1678         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1679         {"#define USEVIEWTINT\n", " viewtint"},
1680         {"#define USECOLORMAPPING\n", " colormapping"},
1681         {"#define USESATURATION\n", " saturation"},
1682         {"#define USEFOGINSIDE\n", " foginside"},
1683         {"#define USEFOGOUTSIDE\n", " fogoutside"},
1684         {"#define USEGAMMARAMPS\n", " gammaramps"},
1685         {"#define USECUBEFILTER\n", " cubefilter"},
1686         {"#define USEGLOW\n", " glow"},
1687         {"#define USEBLOOM\n", " bloom"},
1688         {"#define USESPECULAR\n", " specular"},
1689         {"#define USEPOSTPROCESSING\n", " postprocessing"},
1690         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1691         {"#define USEREFLECTION\n", " reflection"},
1692         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1693         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1694         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1695         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1696         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1697         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1698         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1699         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1700         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1701         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1702         {"#define USEALPHAKILL\n", " alphakill"},
1703 };
1704
1705 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1706 typedef enum shadermode_e
1707 {
1708         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1709         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1710         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1711         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1712         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1713         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1714         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1715         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1716         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1717         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1718         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1719         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1720         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1721         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1722         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1723         SHADERMODE_COUNT
1724 }
1725 shadermode_t;
1726
1727 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1728 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
1729 {
1730         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1731         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1732         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1733         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1734         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1735         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1736         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1737         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1738         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1739         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1740         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1741         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1742         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1743         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1744         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1745 };
1746
1747 #ifdef SUPPORTCG
1748 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
1749 {
1750         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
1751         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
1752         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1753         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
1754         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1755         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
1756         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1757         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1758         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1759         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1760         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
1761         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
1762         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
1763         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1764         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1765 };
1766 #endif
1767
1768 struct r_glsl_permutation_s;
1769 typedef struct r_glsl_permutation_s
1770 {
1771         /// hash lookup data
1772         struct r_glsl_permutation_s *hashnext;
1773         unsigned int mode;
1774         unsigned int permutation;
1775
1776         /// indicates if we have tried compiling this permutation already
1777         qboolean compiled;
1778         /// 0 if compilation failed
1779         int program;
1780         /// locations of detected uniforms in program object, or -1 if not found
1781         int loc_Texture_First;
1782         int loc_Texture_Second;
1783         int loc_Texture_GammaRamps;
1784         int loc_Texture_Normal;
1785         int loc_Texture_Color;
1786         int loc_Texture_Gloss;
1787         int loc_Texture_Glow;
1788         int loc_Texture_SecondaryNormal;
1789         int loc_Texture_SecondaryColor;
1790         int loc_Texture_SecondaryGloss;
1791         int loc_Texture_SecondaryGlow;
1792         int loc_Texture_Pants;
1793         int loc_Texture_Shirt;
1794         int loc_Texture_FogMask;
1795         int loc_Texture_Lightmap;
1796         int loc_Texture_Deluxemap;
1797         int loc_Texture_Attenuation;
1798         int loc_Texture_Cube;
1799         int loc_Texture_Refraction;
1800         int loc_Texture_Reflection;
1801         int loc_Texture_ShadowMapRect;
1802         int loc_Texture_ShadowMapCube;
1803         int loc_Texture_ShadowMap2D;
1804         int loc_Texture_CubeProjection;
1805         int loc_Texture_ScreenDepth;
1806         int loc_Texture_ScreenNormalMap;
1807         int loc_Texture_ScreenDiffuse;
1808         int loc_Texture_ScreenSpecular;
1809         int loc_Alpha;
1810         int loc_BloomBlur_Parameters;
1811         int loc_ClientTime;
1812         int loc_Color_Ambient;
1813         int loc_Color_Diffuse;
1814         int loc_Color_Specular;
1815         int loc_Color_Glow;
1816         int loc_Color_Pants;
1817         int loc_Color_Shirt;
1818         int loc_DeferredColor_Ambient;
1819         int loc_DeferredColor_Diffuse;
1820         int loc_DeferredColor_Specular;
1821         int loc_DeferredMod_Diffuse;
1822         int loc_DeferredMod_Specular;
1823         int loc_DistortScaleRefractReflect;
1824         int loc_EyePosition;
1825         int loc_FogColor;
1826         int loc_FogHeightFade;
1827         int loc_FogPlane;
1828         int loc_FogPlaneViewDist;
1829         int loc_FogRangeRecip;
1830         int loc_LightColor;
1831         int loc_LightDir;
1832         int loc_LightPosition;
1833         int loc_OffsetMapping_Scale;
1834         int loc_PixelSize;
1835         int loc_ReflectColor;
1836         int loc_ReflectFactor;
1837         int loc_ReflectOffset;
1838         int loc_RefractColor;
1839         int loc_Saturation;
1840         int loc_ScreenCenterRefractReflect;
1841         int loc_ScreenScaleRefractReflect;
1842         int loc_ScreenToDepth;
1843         int loc_ShadowMap_Parameters;
1844         int loc_ShadowMap_TextureScale;
1845         int loc_SpecularPower;
1846         int loc_UserVec1;
1847         int loc_UserVec2;
1848         int loc_UserVec3;
1849         int loc_UserVec4;
1850         int loc_ViewTintColor;
1851         int loc_ViewToLight;
1852         int loc_ModelToLight;
1853         int loc_TexMatrix;
1854         int loc_BackgroundTexMatrix;
1855         int loc_ModelViewProjectionMatrix;
1856         int loc_ModelViewMatrix;
1857 }
1858 r_glsl_permutation_t;
1859
1860 #define SHADERPERMUTATION_HASHSIZE 256
1861
1862 /// information about each possible shader permutation
1863 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1864 /// currently selected permutation
1865 r_glsl_permutation_t *r_glsl_permutation;
1866 /// storage for permutations linked in the hash table
1867 memexpandablearray_t r_glsl_permutationarray;
1868
1869 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1870 {
1871         //unsigned int hashdepth = 0;
1872         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1873         r_glsl_permutation_t *p;
1874         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1875         {
1876                 if (p->mode == mode && p->permutation == permutation)
1877                 {
1878                         //if (hashdepth > 10)
1879                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1880                         return p;
1881                 }
1882                 //hashdepth++;
1883         }
1884         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1885         p->mode = mode;
1886         p->permutation = permutation;
1887         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1888         r_glsl_permutationhash[mode][hashindex] = p;
1889         //if (hashdepth > 10)
1890         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1891         return p;
1892 }
1893
1894 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1895 {
1896         char *shaderstring;
1897         if (!filename || !filename[0])
1898                 return NULL;
1899         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1900         if (shaderstring)
1901         {
1902                 if (printfromdisknotice)
1903                         Con_DPrintf("from disk %s... ", filename);
1904                 return shaderstring;
1905         }
1906         else if (!strcmp(filename, "glsl/default.glsl"))
1907         {
1908                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1909                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1910         }
1911         return shaderstring;
1912 }
1913
1914 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1915 {
1916         int i;
1917         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1918         int vertstrings_count = 0;
1919         int geomstrings_count = 0;
1920         int fragstrings_count = 0;
1921         char *vertexstring, *geometrystring, *fragmentstring;
1922         const char *vertstrings_list[32+3];
1923         const char *geomstrings_list[32+3];
1924         const char *fragstrings_list[32+3];
1925         char permutationname[256];
1926
1927         if (p->compiled)
1928                 return;
1929         p->compiled = true;
1930         p->program = 0;
1931
1932         permutationname[0] = 0;
1933         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1934         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1935         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1936
1937         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1938
1939         // the first pretext is which type of shader to compile as
1940         // (later these will all be bound together as a program object)
1941         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1942         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1943         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1944
1945         // the second pretext is the mode (for example a light source)
1946         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1947         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1948         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1949         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1950
1951         // now add all the permutation pretexts
1952         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1953         {
1954                 if (permutation & (1<<i))
1955                 {
1956                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1957                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1958                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1959                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1960                 }
1961                 else
1962                 {
1963                         // keep line numbers correct
1964                         vertstrings_list[vertstrings_count++] = "\n";
1965                         geomstrings_list[geomstrings_count++] = "\n";
1966                         fragstrings_list[fragstrings_count++] = "\n";
1967                 }
1968         }
1969
1970         // now append the shader text itself
1971         vertstrings_list[vertstrings_count++] = vertexstring;
1972         geomstrings_list[geomstrings_count++] = geometrystring;
1973         fragstrings_list[fragstrings_count++] = fragmentstring;
1974
1975         // if any sources were NULL, clear the respective list
1976         if (!vertexstring)
1977                 vertstrings_count = 0;
1978         if (!geometrystring)
1979                 geomstrings_count = 0;
1980         if (!fragmentstring)
1981                 fragstrings_count = 0;
1982
1983         // compile the shader program
1984         if (vertstrings_count + geomstrings_count + fragstrings_count)
1985                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1986         if (p->program)
1987         {
1988                 CHECKGLERROR
1989                 qglUseProgramObjectARB(p->program);CHECKGLERROR
1990                 // look up all the uniform variable names we care about, so we don't
1991                 // have to look them up every time we set them
1992
1993                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
1994                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
1995                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1996                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
1997                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
1998                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1999                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
2000                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
2001                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
2002                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
2003                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
2004                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
2005                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
2006                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
2007                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
2008                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
2009                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
2010                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
2011                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
2012                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
2013                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
2014                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
2015                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
2016                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
2017                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
2018                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
2019                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
2020                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
2021                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
2022                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
2023                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
2024                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
2025                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
2026                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
2027                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
2028                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
2029                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
2030                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
2031                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
2032                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
2033                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
2034                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
2035                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
2036                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
2037                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
2038                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
2039                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
2040                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
2041                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
2042                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
2043                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
2044                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
2045                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
2046                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
2047                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
2048                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
2049                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
2050                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
2051                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
2052                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
2053                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2054                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2055                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2056                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2057                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
2058                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
2059                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
2060                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
2061                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
2062                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
2063                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
2064                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
2065                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
2066                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
2067                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
2068                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
2069                 // initialize the samplers to refer to the texture units we use
2070                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
2071                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
2072                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
2073                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
2074                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
2075                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
2076                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
2077                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2078                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2079                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2080                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
2081                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
2082                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
2083                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
2084                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
2085                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
2086                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
2087                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
2088                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
2089                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
2090                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
2091                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
2092                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
2093                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2094                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
2095                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2096                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
2097                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2098                 CHECKGLERROR
2099                 if (developer.integer)
2100                         Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2101         }
2102         else
2103                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
2104
2105         // free the strings
2106         if (vertexstring)
2107                 Mem_Free(vertexstring);
2108         if (geometrystring)
2109                 Mem_Free(geometrystring);
2110         if (fragmentstring)
2111                 Mem_Free(fragmentstring);
2112 }
2113
2114 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
2115 {
2116         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2117         if (r_glsl_permutation != perm)
2118         {
2119                 r_glsl_permutation = perm;
2120                 if (!r_glsl_permutation->program)
2121                 {
2122                         if (!r_glsl_permutation->compiled)
2123                                 R_GLSL_CompilePermutation(perm, mode, permutation);
2124                         if (!r_glsl_permutation->program)
2125                         {
2126                                 // remove features until we find a valid permutation
2127                                 int i;
2128                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2129                                 {
2130                                         // reduce i more quickly whenever it would not remove any bits
2131                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2132                                         if (!(permutation & j))
2133                                                 continue;
2134                                         permutation -= j;
2135                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2136                                         if (!r_glsl_permutation->compiled)
2137                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
2138                                         if (r_glsl_permutation->program)
2139                                                 break;
2140                                 }
2141                                 if (i >= SHADERPERMUTATION_COUNT)
2142                                 {
2143                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2144                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2145                                         qglUseProgramObjectARB(0);CHECKGLERROR
2146                                         return; // no bit left to clear, entire mode is broken
2147                                 }
2148                         }
2149                 }
2150                 CHECKGLERROR
2151                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2152         }
2153         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
2154 }
2155
2156 #ifdef SUPPORTCG
2157 #include <Cg/cgGL.h>
2158 struct r_cg_permutation_s;
2159 typedef struct r_cg_permutation_s
2160 {
2161         /// hash lookup data
2162         struct r_cg_permutation_s *hashnext;
2163         unsigned int mode;
2164         unsigned int permutation;
2165
2166         /// indicates if we have tried compiling this permutation already
2167         qboolean compiled;
2168         /// 0 if compilation failed
2169         CGprogram vprogram;
2170         CGprogram fprogram;
2171         /// locations of detected parameters in programs, or NULL if not found
2172         CGparameter vp_EyePosition;
2173         CGparameter vp_FogPlane;
2174         CGparameter vp_LightDir;
2175         CGparameter vp_LightPosition;
2176         CGparameter vp_ModelToLight;
2177         CGparameter vp_TexMatrix;
2178         CGparameter vp_BackgroundTexMatrix;
2179         CGparameter vp_ModelViewProjectionMatrix;
2180         CGparameter vp_ModelViewMatrix;
2181
2182         CGparameter fp_Texture_First;
2183         CGparameter fp_Texture_Second;
2184         CGparameter fp_Texture_GammaRamps;
2185         CGparameter fp_Texture_Normal;
2186         CGparameter fp_Texture_Color;
2187         CGparameter fp_Texture_Gloss;
2188         CGparameter fp_Texture_Glow;
2189         CGparameter fp_Texture_SecondaryNormal;
2190         CGparameter fp_Texture_SecondaryColor;
2191         CGparameter fp_Texture_SecondaryGloss;
2192         CGparameter fp_Texture_SecondaryGlow;
2193         CGparameter fp_Texture_Pants;
2194         CGparameter fp_Texture_Shirt;
2195         CGparameter fp_Texture_FogMask;
2196         CGparameter fp_Texture_Lightmap;
2197         CGparameter fp_Texture_Deluxemap;
2198         CGparameter fp_Texture_Attenuation;
2199         CGparameter fp_Texture_Cube;
2200         CGparameter fp_Texture_Refraction;
2201         CGparameter fp_Texture_Reflection;
2202         CGparameter fp_Texture_ShadowMapRect;
2203         CGparameter fp_Texture_ShadowMapCube;
2204         CGparameter fp_Texture_ShadowMap2D;
2205         CGparameter fp_Texture_CubeProjection;
2206         CGparameter fp_Texture_ScreenDepth;
2207         CGparameter fp_Texture_ScreenNormalMap;
2208         CGparameter fp_Texture_ScreenDiffuse;
2209         CGparameter fp_Texture_ScreenSpecular;
2210         CGparameter fp_Alpha;
2211         CGparameter fp_BloomBlur_Parameters;
2212         CGparameter fp_ClientTime;
2213         CGparameter fp_Color_Ambient;
2214         CGparameter fp_Color_Diffuse;
2215         CGparameter fp_Color_Specular;
2216         CGparameter fp_Color_Glow;
2217         CGparameter fp_Color_Pants;
2218         CGparameter fp_Color_Shirt;
2219         CGparameter fp_DeferredColor_Ambient;
2220         CGparameter fp_DeferredColor_Diffuse;
2221         CGparameter fp_DeferredColor_Specular;
2222         CGparameter fp_DeferredMod_Diffuse;
2223         CGparameter fp_DeferredMod_Specular;
2224         CGparameter fp_DistortScaleRefractReflect;
2225         CGparameter fp_EyePosition;
2226         CGparameter fp_FogColor;
2227         CGparameter fp_FogHeightFade;
2228         CGparameter fp_FogPlane;
2229         CGparameter fp_FogPlaneViewDist;
2230         CGparameter fp_FogRangeRecip;
2231         CGparameter fp_LightColor;
2232         CGparameter fp_LightDir;
2233         CGparameter fp_LightPosition;
2234         CGparameter fp_OffsetMapping_Scale;
2235         CGparameter fp_PixelSize;
2236         CGparameter fp_ReflectColor;
2237         CGparameter fp_ReflectFactor;
2238         CGparameter fp_ReflectOffset;
2239         CGparameter fp_RefractColor;
2240         CGparameter fp_Saturation;
2241         CGparameter fp_ScreenCenterRefractReflect;
2242         CGparameter fp_ScreenScaleRefractReflect;
2243         CGparameter fp_ScreenToDepth;
2244         CGparameter fp_ShadowMap_Parameters;
2245         CGparameter fp_ShadowMap_TextureScale;
2246         CGparameter fp_SpecularPower;
2247         CGparameter fp_UserVec1;
2248         CGparameter fp_UserVec2;
2249         CGparameter fp_UserVec3;
2250         CGparameter fp_UserVec4;
2251         CGparameter fp_ViewTintColor;
2252         CGparameter fp_ViewToLight;
2253 }
2254 r_cg_permutation_t;
2255
2256 /// information about each possible shader permutation
2257 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
2258 /// currently selected permutation
2259 r_cg_permutation_t *r_cg_permutation;
2260 /// storage for permutations linked in the hash table
2261 memexpandablearray_t r_cg_permutationarray;
2262
2263 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
2264 {
2265         //unsigned int hashdepth = 0;
2266         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
2267         r_cg_permutation_t *p;
2268         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
2269         {
2270                 if (p->mode == mode && p->permutation == permutation)
2271                 {
2272                         //if (hashdepth > 10)
2273                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
2274                         return p;
2275                 }
2276                 //hashdepth++;
2277         }
2278         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
2279         p->mode = mode;
2280         p->permutation = permutation;
2281         p->hashnext = r_cg_permutationhash[mode][hashindex];
2282         r_cg_permutationhash[mode][hashindex] = p;
2283         //if (hashdepth > 10)
2284         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
2285         return p;
2286 }
2287
2288 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
2289 {
2290         char *shaderstring;
2291         if (!filename || !filename[0])
2292                 return NULL;
2293         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
2294         if (shaderstring)
2295         {
2296                 if (printfromdisknotice)
2297                         Con_DPrintf("from disk %s... ", filename);
2298                 return shaderstring;
2299         }
2300         else if (!strcmp(filename, "cg/default.cg"))
2301         {
2302                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
2303                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
2304         }
2305         return shaderstring;
2306 }
2307
2308 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
2309 {
2310         int i;
2311         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
2312         int vertstrings_count = 0, vertstring_length = 0;
2313         int geomstrings_count = 0, geomstring_length = 0;
2314         int fragstrings_count = 0, fragstring_length = 0;
2315         char *t;
2316         char *vertexstring, *geometrystring, *fragmentstring;
2317         char *vertstring, *geomstring, *fragstring;
2318         const char *vertstrings_list[32+3];
2319         const char *geomstrings_list[32+3];
2320         const char *fragstrings_list[32+3];
2321         char permutationname[256];
2322
2323         if (p->compiled)
2324                 return;
2325         p->compiled = true;
2326         p->vprogram = NULL;
2327         p->fprogram = NULL;
2328
2329         permutationname[0] = 0;
2330         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
2331         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
2332         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
2333
2334         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
2335
2336         // the first pretext is which type of shader to compile as
2337         // (later these will all be bound together as a program object)
2338         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
2339         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
2340         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
2341
2342         // the second pretext is the mode (for example a light source)
2343         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
2344         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
2345         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
2346         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
2347
2348         // now add all the permutation pretexts
2349         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2350         {
2351                 if (permutation & (1<<i))
2352                 {
2353                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
2354                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
2355                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
2356                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
2357                 }
2358                 else
2359                 {
2360                         // keep line numbers correct
2361                         vertstrings_list[vertstrings_count++] = "\n";
2362                         geomstrings_list[geomstrings_count++] = "\n";
2363                         fragstrings_list[fragstrings_count++] = "\n";
2364                 }
2365         }
2366
2367         // now append the shader text itself
2368         vertstrings_list[vertstrings_count++] = vertexstring;
2369         geomstrings_list[geomstrings_count++] = geometrystring;
2370         fragstrings_list[fragstrings_count++] = fragmentstring;
2371
2372         // if any sources were NULL, clear the respective list
2373         if (!vertexstring)
2374                 vertstrings_count = 0;
2375         if (!geometrystring)
2376                 geomstrings_count = 0;
2377         if (!fragmentstring)
2378                 fragstrings_count = 0;
2379
2380         vertstring_length = 0;
2381         for (i = 0;i < vertstrings_count;i++)
2382                 vertstring_length += strlen(vertstrings_list[i]);
2383         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
2384         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
2385                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
2386
2387         geomstring_length = 0;
2388         for (i = 0;i < geomstrings_count;i++)
2389                 geomstring_length += strlen(geomstrings_list[i]);
2390         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
2391         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
2392                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
2393
2394         fragstring_length = 0;
2395         for (i = 0;i < fragstrings_count;i++)
2396                 fragstring_length += strlen(fragstrings_list[i]);
2397         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
2398         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
2399                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
2400
2401         // compile the shader program
2402         if (vertstring[0] || geomstring[0] || fragstring[0])
2403         {
2404                 if (vertstring[0])
2405                         p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL);
2406                 if (fragstring[0])
2407                         p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL);
2408         }
2409
2410         if (p->vprogram)
2411         {
2412                 cgGLBindProgram(p->vprogram);
2413                 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2414         }
2415         else
2416                 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2417         if (p->fprogram)
2418         {
2419                 cgGLBindProgram(p->fprogram);
2420                 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2421         }
2422         else
2423                 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2424
2425         if (p->vprogram || p->fprogram)
2426         {
2427                 // look up all the uniform variable names we care about, so we don't
2428                 // have to look them up every time we set them
2429                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
2430                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
2431                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
2432                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
2433                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
2434                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
2435                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
2436                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
2437                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
2438
2439                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
2440                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
2441                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
2442                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
2443                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
2444                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
2445                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
2446                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
2447                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
2448                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
2449                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
2450                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
2451                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
2452                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
2453                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
2454                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
2455                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
2456                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
2457                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
2458                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
2459                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
2460                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
2461                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
2462                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
2463                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
2464                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
2465                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
2466                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
2467                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
2468                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
2469                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
2470                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
2471                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
2472                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
2473                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
2474                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
2475                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
2476                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
2477                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
2478                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
2479                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
2480                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
2481                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
2482                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
2483                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
2484                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
2485                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
2486                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
2487                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
2488                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
2489                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
2490                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
2491                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
2492                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
2493                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
2494                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
2495                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
2496                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
2497                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
2498                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
2499                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
2500                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
2501                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
2502                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
2503                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
2504                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
2505                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
2506                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
2507                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
2508                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
2509                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
2510                 CHECKGLERROR
2511                 if (developer.integer)
2512                         Con_Printf("^5CG shader %s compiled.\n", permutationname);
2513         }
2514         else
2515                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
2516
2517         // free the strings
2518         if (vertstring)
2519                 Mem_Free(vertstring);
2520         if (geomstring)
2521                 Mem_Free(geomstring);
2522         if (fragstring)
2523                 Mem_Free(fragstring);
2524         if (vertexstring)
2525                 Mem_Free(vertexstring);
2526         if (geometrystring)
2527                 Mem_Free(geometrystring);
2528         if (fragmentstring)
2529                 Mem_Free(fragmentstring);
2530 }
2531
2532 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
2533 {
2534         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
2535         if (r_cg_permutation != perm)
2536         {
2537                 r_cg_permutation = perm;
2538                 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));
2539                 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2540                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
2541                 {
2542                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2543                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2544                         if (!r_cg_permutation->compiled)
2545                                 R_CG_CompilePermutation(perm, mode, permutation);
2546                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
2547                         {
2548                                 // remove features until we find a valid permutation
2549                                 int i;
2550                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2551                                 {
2552                                         // reduce i more quickly whenever it would not remove any bits
2553                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2554                                         if (!(permutation & j))
2555                                                 continue;
2556                                         permutation -= j;
2557                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
2558                                         if (!r_cg_permutation->compiled)
2559                                                 R_CG_CompilePermutation(perm, mode, permutation);
2560                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
2561                                                 break;
2562                                 }
2563                                 if (i >= SHADERPERMUTATION_COUNT)
2564                                 {
2565                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2566                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
2567                                         return; // no bit left to clear, entire mode is broken
2568                                 }
2569                         }
2570                 }
2571                 CHECKGLERROR
2572                 if (r_cg_permutation->vprogram)
2573                 {
2574                         cgGLBindProgram(r_cg_permutation->vprogram);
2575                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2576                 }
2577                 else
2578                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2579                 if (r_cg_permutation->fprogram)
2580                 {
2581                         cgGLBindProgram(r_cg_permutation->fprogram);
2582                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2583                 }
2584                 else
2585                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2586         }
2587         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);
2588 }
2589 #endif
2590
2591 void R_GLSL_Restart_f(void)
2592 {
2593         unsigned int i, limit;
2594         r_glsl_permutation_t *p;
2595         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2596         for (i = 0;i < limit;i++)
2597         {
2598                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2599                 {
2600                         GL_Backend_FreeProgram(p->program);
2601                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2602                 }
2603         }
2604         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2605 #ifdef SUPPORTCG
2606         if (vid.cgcontext)
2607         {
2608                 r_cg_permutation_t *p;
2609                 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
2610                 for (i = 0;i < limit;i++)
2611                 {
2612                         if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
2613                         {
2614                                 if (p->vprogram)
2615                                         cgDestroyProgram(p->vprogram);
2616                                 if (p->fprogram)
2617                                         cgDestroyProgram(p->fprogram);
2618                                 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
2619                         }
2620                 }
2621                 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
2622         }
2623 #endif
2624 }
2625
2626 void R_GLSL_DumpShader_f(void)
2627 {
2628         int i;
2629         qfile_t *file;
2630
2631         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2632         if (file)
2633         {
2634                 FS_Print(file, "/* The engine may define the following macros:\n");
2635                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2636                 for (i = 0;i < SHADERMODE_COUNT;i++)
2637                         FS_Print(file, glslshadermodeinfo[i].pretext);
2638                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2639                         FS_Print(file, shaderpermutationinfo[i].pretext);
2640                 FS_Print(file, "*/\n");
2641                 FS_Print(file, builtinshaderstring);
2642                 FS_Close(file);
2643                 Con_Printf("glsl/default.glsl written\n");
2644         }
2645         else
2646                 Con_Printf("failed to write to glsl/default.glsl\n");
2647
2648 #ifdef SUPPORTCG
2649         file = FS_OpenRealFile("cg/default.cg", "w", false);
2650         if (file)
2651         {
2652                 FS_Print(file, "/* The engine may define the following macros:\n");
2653                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2654                 for (i = 0;i < SHADERMODE_COUNT;i++)
2655                         FS_Print(file, cgshadermodeinfo[i].pretext);
2656                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2657                         FS_Print(file, shaderpermutationinfo[i].pretext);
2658                 FS_Print(file, "*/\n");
2659                 FS_Print(file, builtincgshaderstring);
2660                 FS_Close(file);
2661                 Con_Printf("cg/default.cg written\n");
2662         }
2663         else
2664                 Con_Printf("failed to write to cg/default.cg\n");
2665 #endif
2666 }
2667
2668 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
2669 {
2670         if (!second)
2671                 texturemode = GL_MODULATE;
2672         switch (vid.renderpath)
2673         {
2674         case RENDERPATH_GL20:
2675                 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))));
2676                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(first ));
2677                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, R_GetTexture(second));
2678                 break;
2679         case RENDERPATH_CGGL:
2680 #ifdef SUPPORTCG
2681                 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))));
2682                 if (r_cg_permutation->fp_Texture_First ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First , R_GetTexture(first ));
2683                 if (r_cg_permutation->fp_Texture_Second) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second, R_GetTexture(second));
2684 #endif
2685                 break;
2686         case RENDERPATH_GL13:
2687                 R_Mesh_TexBind(0, R_GetTexture(first ));
2688                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2689                 R_Mesh_TexBind(1, R_GetTexture(second));
2690                 if (second)
2691                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2692                 break;
2693         case RENDERPATH_GL11:
2694                 R_Mesh_TexBind(0, R_GetTexture(first ));
2695                 break;
2696         }
2697 }
2698
2699 void R_SetupShader_DepthOrShadow(void)
2700 {
2701         switch (vid.renderpath)
2702         {
2703         case RENDERPATH_GL20:
2704                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
2705                 break;
2706         case RENDERPATH_CGGL:
2707 #ifdef SUPPORTCG
2708                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
2709 #endif
2710                 break;
2711         case RENDERPATH_GL13:
2712                 R_Mesh_TexBind(0, 0);
2713                 R_Mesh_TexBind(1, 0);
2714                 break;
2715         case RENDERPATH_GL11:
2716                 R_Mesh_TexBind(0, 0);
2717                 break;
2718         }
2719 }
2720
2721 void R_SetupShader_ShowDepth(void)
2722 {
2723         switch (vid.renderpath)
2724         {
2725         case RENDERPATH_GL20:
2726                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
2727                 break;
2728         case RENDERPATH_CGGL:
2729 #ifdef SUPPORTCG
2730                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
2731 #endif
2732                 break;
2733         case RENDERPATH_GL13:
2734                 break;
2735         case RENDERPATH_GL11:
2736                 break;
2737         }
2738 }
2739
2740 extern qboolean r_shadow_usingdeferredprepass;
2741 extern cvar_t r_shadow_deferred_8bitrange;
2742 extern rtexture_t *r_shadow_attenuationgradienttexture;
2743 extern rtexture_t *r_shadow_attenuation2dtexture;
2744 extern rtexture_t *r_shadow_attenuation3dtexture;
2745 extern qboolean r_shadow_usingshadowmaprect;
2746 extern qboolean r_shadow_usingshadowmapcube;
2747 extern qboolean r_shadow_usingshadowmap2d;
2748 extern float r_shadow_shadowmap_texturescale[2];
2749 extern float r_shadow_shadowmap_parameters[4];
2750 extern qboolean r_shadow_shadowmapvsdct;
2751 extern qboolean r_shadow_shadowmapsampler;
2752 extern int r_shadow_shadowmappcf;
2753 extern rtexture_t *r_shadow_shadowmaprectangletexture;
2754 extern rtexture_t *r_shadow_shadowmap2dtexture;
2755 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
2756 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2757 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2758 extern int r_shadow_prepass_width;
2759 extern int r_shadow_prepass_height;
2760 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2761 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2762 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2763 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2764 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2765 {
2766         // select a permutation of the lighting shader appropriate to this
2767         // combination of texture, entity, light source, and fogging, only use the
2768         // minimum features necessary to avoid wasting rendering time in the
2769         // fragment shader on features that are not being used
2770         unsigned int permutation = 0;
2771         unsigned int mode = 0;
2772         float m16f[16];
2773         // TODO: implement geometry-shader based shadow volumes someday
2774         if (r_glsl_offsetmapping.integer)
2775         {
2776                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2777                 if (r_glsl_offsetmapping_reliefmapping.integer)
2778                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2779         }
2780         if (rsurfacepass == RSURFPASS_BACKGROUND)
2781         {
2782                 // distorted background
2783                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2784                         mode = SHADERMODE_WATER;
2785                 else
2786                         mode = SHADERMODE_REFRACTION;
2787         }
2788         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2789         {
2790                 // normalmap (deferred prepass), may use alpha test on diffuse
2791                 mode = SHADERMODE_DEFERREDGEOMETRY;
2792                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2793                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2794                 if (r_glsl_offsetmapping.integer)
2795                 {
2796                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2797                         if (r_glsl_offsetmapping_reliefmapping.integer)
2798                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2799                 }
2800         }
2801         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2802         {
2803                 // light source
2804                 mode = SHADERMODE_LIGHTSOURCE;
2805                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2806                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2807                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2808                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2809                 if (diffusescale > 0)
2810                         permutation |= SHADERPERMUTATION_DIFFUSE;
2811                 if (specularscale > 0)
2812                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2813                 if (r_refdef.fogenabled)
2814                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2815                 if (rsurface.texture->colormapping)
2816                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2817                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2818                 {
2819                         if (r_shadow_usingshadowmaprect)
2820                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2821                         if (r_shadow_usingshadowmap2d)
2822                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2823                         if (r_shadow_usingshadowmapcube)
2824                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2825                         else if(r_shadow_shadowmapvsdct)
2826                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2827
2828                         if (r_shadow_shadowmapsampler)
2829                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2830                         if (r_shadow_shadowmappcf > 1)
2831                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2832                         else if (r_shadow_shadowmappcf)
2833                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2834                 }
2835         }
2836         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2837         {
2838                 // unshaded geometry (fullbright or ambient model lighting)
2839                 mode = SHADERMODE_FLATCOLOR;
2840                 ambientscale = diffusescale = specularscale = 0;
2841                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2842                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2843                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2844                         permutation |= SHADERPERMUTATION_GLOW;
2845                 if (r_refdef.fogenabled)
2846                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2847                 if (rsurface.texture->colormapping)
2848                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2849                 if (r_glsl_offsetmapping.integer)
2850                 {
2851                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2852                         if (r_glsl_offsetmapping_reliefmapping.integer)
2853                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2854                 }
2855                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2856                         permutation |= SHADERPERMUTATION_REFLECTION;
2857         }
2858         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2859         {
2860                 // directional model lighting
2861                 mode = SHADERMODE_LIGHTDIRECTION;
2862                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2863                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2864                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2865                         permutation |= SHADERPERMUTATION_GLOW;
2866                 permutation |= SHADERPERMUTATION_DIFFUSE;
2867                 if (specularscale > 0)
2868                         permutation |= SHADERPERMUTATION_SPECULAR;
2869                 if (r_refdef.fogenabled)
2870                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2871                 if (rsurface.texture->colormapping)
2872                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2873                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2874                         permutation |= SHADERPERMUTATION_REFLECTION;
2875                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2876                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2877         }
2878         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2879         {
2880                 // ambient model lighting
2881                 mode = SHADERMODE_LIGHTDIRECTION;
2882                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2883                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2884                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2885                         permutation |= SHADERPERMUTATION_GLOW;
2886                 if (r_refdef.fogenabled)
2887                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2888                 if (rsurface.texture->colormapping)
2889                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2890                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2891                         permutation |= SHADERPERMUTATION_REFLECTION;
2892                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2893                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2894         }
2895         else
2896         {
2897                 // lightmapped wall
2898                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2899                 {
2900                         // deluxemapping (light direction texture)
2901                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2902                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2903                         else
2904                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2905                         permutation |= SHADERPERMUTATION_DIFFUSE;
2906                         if (specularscale > 0)
2907                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2908                 }
2909                 else if (r_glsl_deluxemapping.integer >= 2)
2910                 {
2911                         // fake deluxemapping (uniform light direction in tangentspace)
2912                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2913                         permutation |= SHADERPERMUTATION_DIFFUSE;
2914                         if (specularscale > 0)
2915                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2916                 }
2917                 else if (rsurface.uselightmaptexture)
2918                 {
2919                         // ordinary lightmapping (q1bsp, q3bsp)
2920                         mode = SHADERMODE_LIGHTMAP;
2921                 }
2922                 else
2923                 {
2924                         // ordinary vertex coloring (q3bsp)
2925                         mode = SHADERMODE_VERTEXCOLOR;
2926                 }
2927                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2928                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2929                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2930                         permutation |= SHADERPERMUTATION_GLOW;
2931                 if (r_refdef.fogenabled)
2932                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2933                 if (rsurface.texture->colormapping)
2934                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2935                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2936                         permutation |= SHADERPERMUTATION_REFLECTION;
2937                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2938                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2939         }
2940         if(permutation & SHADERPERMUTATION_SPECULAR)
2941                 if(r_shadow_glossexact.integer)
2942                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2943         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
2944                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2945         switch(vid.renderpath)
2946         {
2947         case RENDERPATH_GL20:
2948                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2949                 if (mode == SHADERMODE_LIGHTSOURCE)
2950                 {
2951                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2952                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2953                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2954                         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);
2955                         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);
2956                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
2957         
2958                         // additive passes are only darkened by fog, not tinted
2959                         if (r_glsl_permutation->loc_FogColor >= 0)
2960                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2961                         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]);
2962                         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]);
2963                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2964                 }
2965                 else
2966                 {
2967                         if (mode == SHADERMODE_FLATCOLOR)
2968                         {
2969                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
2970                         }
2971                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2972                         {
2973                                 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]);
2974                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
2975                                 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);
2976                                 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);
2977                                 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);
2978                                 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]);
2979                                 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]);
2980                         }
2981                         else
2982                         {
2983                                 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]);
2984                                 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]);
2985                                 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);
2986                                 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);
2987                                 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);
2988                         }
2989                         // additive passes are only darkened by fog, not tinted
2990                         if (r_glsl_permutation->loc_FogColor >= 0)
2991                         {
2992                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2993                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2994                                 else
2995                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2996                         }
2997                         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);
2998                         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]);
2999                         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]);
3000                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
3001                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
3002                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3003                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
3004                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3005                 }
3006                 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3007                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
3008                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
3009                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3010                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
3011                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3012                 if (r_glsl_permutation->loc_Color_Pants >= 0)
3013                 {
3014                         if (rsurface.texture->pantstexture)
3015                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3016                         else
3017                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
3018                 }
3019                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
3020                 {
3021                         if (rsurface.texture->shirttexture)
3022                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3023                         else
3024                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
3025                 }
3026                 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]);
3027                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
3028                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
3029                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
3030                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
3031                 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]);
3032
3033         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             ,          R_GetTexture(r_texture_white                                     ));
3034         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            ,          R_GetTexture(r_texture_white                                     ));
3035         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        ,          R_GetTexture(r_texture_gammaramps                                ));
3036                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            ,          R_GetTexture(rsurface.texture->nmaptexture                       ));
3037                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             ,          R_GetTexture(rsurface.texture->basetexture                       ));
3038                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             ,          R_GetTexture(rsurface.texture->glosstexture                      ));
3039                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              ,          R_GetTexture(rsurface.texture->glowtexture                       ));
3040                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  ,          R_GetTexture(rsurface.texture->backgroundnmaptexture             ));
3041                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   ,          R_GetTexture(rsurface.texture->backgroundbasetexture             ));
3042                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   ,          R_GetTexture(rsurface.texture->backgroundglosstexture            ));
3043                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    ,          R_GetTexture(rsurface.texture->backgroundglowtexture             ));
3044                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             ,          R_GetTexture(rsurface.texture->pantstexture                      ));
3045                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             ,          R_GetTexture(rsurface.texture->shirttexture                      ));
3046                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           ,          R_GetTexture(r_texture_fogattenuation                            ));
3047                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          ,          R_GetTexture(r_texture_white                                     ));
3048                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          ,          R_GetTexture(r_texture_blanknormalmap                            ));
3049                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       ,          R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3050                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        ,          R_GetTexture(r_texture_white                                     ));
3051                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        ,          R_GetTexture(r_texture_white                                     ));
3052                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH    , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3053                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3054                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE  , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture              ));
3055                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture             ));
3056                 if (rsurface.rtlight)
3057                 {
3058                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBindAll(GL20TU_CUBE           , 0, 0,    R_GetTexture(rsurface.rtlight->currentcubemap                    ), 0);
3059                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT  , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3060                         if (r_shadow_usingshadowmapcube)
3061                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE  , 0, 0,    R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
3062                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       ,          R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3063                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0,    R_GetTexture(r_shadow_shadowmapvsdcttexture                      ), 0);
3064                 }
3065                 CHECKGLERROR
3066                 break;
3067         case RENDERPATH_CGGL:
3068 #ifdef SUPPORTCG
3069                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3070                 if (mode == SHADERMODE_LIGHTSOURCE)
3071                 {
3072                         if (r_cg_permutation->vp_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}
3073                         if (r_cg_permutation->vp_LightPosition >= 0) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
3074                 }
3075                 else
3076                 {
3077                         if (mode == SHADERMODE_LIGHTDIRECTION)
3078                         {
3079                                 if (r_cg_permutation->vp_LightDir >= 0) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
3080                         }
3081                 }
3082                 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);
3083                 if (r_cg_permutation->vp_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}
3084                 if (r_cg_permutation->vp_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}
3085                 if (r_cg_permutation->vp_EyePosition >= 0) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3086                 if (r_cg_permutation->vp_FogPlane >= 0) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3087                 CHECKGLERROR
3088
3089                 if (mode == SHADERMODE_LIGHTSOURCE)
3090                 {
3091                         if (r_cg_permutation->fp_LightPosition >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
3092                         if (r_cg_permutation->fp_LightColor >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
3093                         if (r_cg_permutation->fp_Color_Ambient >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
3094                         if (r_cg_permutation->fp_Color_Diffuse >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
3095                         if (r_cg_permutation->fp_Color_Specular >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);
3096
3097                         // additive passes are only darkened by fog, not tinted
3098                         if (r_cg_permutation->fp_FogColor >= 0)
3099                                 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
3100                         if (r_cg_permutation->fp_ShadowMap_TextureScale >= 0) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3101                         if (r_cg_permutation->fp_ShadowMap_Parameters >= 0) 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]);
3102                         if (r_cg_permutation->fp_SpecularPower >= 0) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3103                 }
3104                 else
3105                 {
3106                         if (mode == SHADERMODE_FLATCOLOR)
3107                         {
3108                                 if (r_cg_permutation->fp_Color_Ambient >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
3109                         }
3110                         else if (mode == SHADERMODE_LIGHTDIRECTION)
3111                         {
3112                                 if (r_cg_permutation->fp_Color_Ambient >= 0) 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]);
3113                                 if (r_cg_permutation->fp_Color_Diffuse >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
3114                                 if (r_cg_permutation->fp_Color_Specular >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
3115                                 if (r_cg_permutation->fp_DeferredMod_Diffuse >= 0) 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);
3116                                 if (r_cg_permutation->fp_DeferredMod_Specular >= 0) 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);
3117                                 if (r_cg_permutation->fp_LightColor >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
3118                                 if (r_cg_permutation->fp_LightDir >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
3119                         }
3120                         else
3121                         {
3122                                 if (r_cg_permutation->fp_Color_Ambient >= 0) 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]);
3123                                 if (r_cg_permutation->fp_Color_Diffuse >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
3124                                 if (r_cg_permutation->fp_Color_Specular >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
3125                                 if (r_cg_permutation->fp_DeferredMod_Diffuse >= 0) 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);
3126                                 if (r_cg_permutation->fp_DeferredMod_Specular >= 0) 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);
3127                         }
3128                         // additive passes are only darkened by fog, not tinted
3129                         if (r_cg_permutation->fp_FogColor >= 0)
3130                         {
3131                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
3132                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
3133                                 else
3134                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
3135                         }
3136                         if (r_cg_permutation->fp_DistortScaleRefractReflect >= 0) 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);
3137                         if (r_cg_permutation->fp_ScreenScaleRefractReflect >= 0) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
3138                         if (r_cg_permutation->fp_ScreenCenterRefractReflect >= 0) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
3139                         if (r_cg_permutation->fp_RefractColor >= 0) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);
3140                         if (r_cg_permutation->fp_ReflectColor >= 0) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);
3141                         if (r_cg_permutation->fp_ReflectFactor >= 0) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3142                         if (r_cg_permutation->fp_ReflectOffset >= 0) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);
3143                         if (r_cg_permutation->fp_SpecularPower >= 0) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3144                 }
3145                 if (r_cg_permutation->fp_Color_Glow >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3146                 if (r_cg_permutation->fp_Alpha >= 0) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);
3147                 if (r_cg_permutation->fp_EyePosition >= 0) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3148                 if (r_cg_permutation->fp_Color_Pants >= 0)
3149                 {
3150                         if (rsurface.texture->pantstexture)
3151                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3152                         else
3153                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
3154                 }
3155                 if (r_cg_permutation->fp_Color_Shirt >= 0)
3156                 {
3157                         if (rsurface.texture->shirttexture)
3158                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3159                         else
3160                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
3161                 }
3162                 if (r_cg_permutation->fp_FogPlane >= 0) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3163                 if (r_cg_permutation->fp_FogPlaneViewDist >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);
3164                 if (r_cg_permutation->fp_FogRangeRecip >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);
3165                 if (r_cg_permutation->fp_FogHeightFade >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);
3166                 if (r_cg_permutation->fp_OffsetMapping_Scale >= 0) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
3167                 if (r_cg_permutation->fp_ScreenToDepth >= 0) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3168
3169         //      if (r_cg_permutation->fp_Texture_First          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First          , R_GetTexture(r_texture_white                                     ));
3170         //      if (r_cg_permutation->fp_Texture_Second         ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second         , R_GetTexture(r_texture_white                                     ));
3171         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_GammaRamps     , R_GetTexture(r_texture_gammaramps                                ));
3172                 if (r_cg_permutation->fp_Texture_Normal         ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Normal         , R_GetTexture(rsurface.texture->nmaptexture                       ));
3173                 if (r_cg_permutation->fp_Texture_Color          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Color          , R_GetTexture(rsurface.texture->basetexture                       ));
3174                 if (r_cg_permutation->fp_Texture_Gloss          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Gloss          , R_GetTexture(rsurface.texture->glosstexture                      ));
3175                 if (r_cg_permutation->fp_Texture_Glow           ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Glow           , R_GetTexture(rsurface.texture->glowtexture                       ));
3176                 if (r_cg_permutation->fp_Texture_SecondaryNormal) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryNormal, R_GetTexture(rsurface.texture->backgroundnmaptexture             ));
3177                 if (r_cg_permutation->fp_Texture_SecondaryColor ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryColor , R_GetTexture(rsurface.texture->backgroundbasetexture             ));
3178                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryGloss , R_GetTexture(rsurface.texture->backgroundglosstexture            ));
3179                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryGlow  , R_GetTexture(rsurface.texture->backgroundglowtexture             ));
3180                 if (r_cg_permutation->fp_Texture_Pants          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Pants          , R_GetTexture(rsurface.texture->pantstexture                      ));
3181                 if (r_cg_permutation->fp_Texture_Shirt          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Shirt          , R_GetTexture(rsurface.texture->shirttexture                      ));
3182                 if (r_cg_permutation->fp_Texture_FogMask        ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_FogMask        , R_GetTexture(r_texture_fogattenuation                            ));
3183                 if (r_cg_permutation->fp_Texture_Lightmap       ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Lightmap       , R_GetTexture(r_texture_white                                     ));
3184                 if (r_cg_permutation->fp_Texture_Deluxemap      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Deluxemap      , R_GetTexture(r_texture_blanknormalmap                            ));
3185                 if (r_cg_permutation->fp_Texture_Attenuation    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Attenuation    , R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3186                 if (r_cg_permutation->fp_Texture_Refraction     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Refraction     , R_GetTexture(r_texture_white                                     ));
3187                 if (r_cg_permutation->fp_Texture_Reflection     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Reflection     , R_GetTexture(r_texture_white                                     ));
3188                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDepth    , R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3189                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3190                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDiffuse  , R_GetTexture(r_shadow_prepasslightingdiffusetexture              ));
3191                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenSpecular , R_GetTexture(r_shadow_prepasslightingspeculartexture             ));
3192                 if (rsurface.rtlight)
3193                 {
3194                         if (r_cg_permutation->fp_Texture_Cube       ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Cube           , R_GetTexture(rsurface.rtlight->currentcubemap                    ));
3195                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapRect  , R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3196                         if (r_shadow_usingshadowmapcube)
3197                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapCube  , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
3198                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMap2D    , R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3199                         if (r_cg_permutation->fp_Texture_CubeProjection ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture                      ));
3200                 }
3201
3202                 CHECKGLERROR
3203 #endif
3204                 break;
3205         case RENDERPATH_GL13:
3206         case RENDERPATH_GL11:
3207                 break;
3208         }
3209 }
3210
3211 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3212 {
3213         // select a permutation of the lighting shader appropriate to this
3214         // combination of texture, entity, light source, and fogging, only use the
3215         // minimum features necessary to avoid wasting rendering time in the
3216         // fragment shader on features that are not being used
3217         unsigned int permutation = 0;
3218         unsigned int mode = 0;
3219         const float *lightcolorbase = rtlight->currentcolor;
3220         float ambientscale = rtlight->ambientscale;
3221         float diffusescale = rtlight->diffusescale;
3222         float specularscale = rtlight->specularscale;
3223         // this is the location of the light in view space
3224         vec3_t viewlightorigin;
3225         // this transforms from view space (camera) to light space (cubemap)
3226         matrix4x4_t viewtolight;
3227         matrix4x4_t lighttoview;
3228         float viewtolight16f[16];
3229         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3230         // light source
3231         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3232         if (rtlight->currentcubemap != r_texture_whitecube)
3233                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3234         if (diffusescale > 0)
3235                 permutation |= SHADERPERMUTATION_DIFFUSE;
3236         if (specularscale > 0)
3237         {
3238                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3239                 if (r_shadow_glossexact.integer)
3240                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
3241         }
3242         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
3243         {
3244                 if (r_shadow_usingshadowmaprect)
3245                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
3246                 if (r_shadow_usingshadowmap2d)
3247                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3248                 if (r_shadow_usingshadowmapcube)
3249                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
3250                 else if(r_shadow_shadowmapvsdct)
3251                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3252
3253                 if (r_shadow_shadowmapsampler)
3254                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3255                 if (r_shadow_shadowmappcf > 1)
3256                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3257                 else if (r_shadow_shadowmappcf)
3258                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3259         }
3260         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3261         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3262         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3263         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3264         switch(vid.renderpath)
3265         {
3266         case RENDERPATH_GL20:
3267                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3268                 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3269                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3270                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3271                 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);
3272                 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);
3273                 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);
3274                 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]);
3275                 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]);
3276                 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));
3277                 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]);
3278
3279                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       ,          R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3280                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH    , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3281                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3282                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBindAll(GL20TU_CUBE           , 0, 0,    R_GetTexture(rsurface.rtlight->currentcubemap                    ), 0);
3283                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT  , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3284                 if (r_shadow_usingshadowmapcube)
3285                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE  , 0, 0,    R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
3286                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       ,          R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3287                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0,    R_GetTexture(r_shadow_shadowmapvsdcttexture                      ), 0);
3288                 break;
3289         case RENDERPATH_CGGL:
3290 #ifdef SUPPORTCG
3291                 R_SetupShader_SetPermutationCG(mode, permutation);
3292                 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);
3293                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3294                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);
3295                 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);
3296                 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);
3297                 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);
3298                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3299                 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]);
3300                 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));
3301                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3302
3303                 if (r_cg_permutation->fp_Texture_Attenuation      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Attenuation    , R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3304                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDepth    , R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3305                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3306                 if (r_cg_permutation->fp_Texture_Cube             ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Cube           , R_GetTexture(rsurface.rtlight->currentcubemap                    ));
3307                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapRect  , R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3308                 if (r_shadow_usingshadowmapcube)
3309                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapCube  , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
3310                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMap2D    , R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3311                 if (r_cg_permutation->fp_Texture_CubeProjection   ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture                      ));
3312 #endif
3313                 break;
3314         case RENDERPATH_GL13:
3315         case RENDERPATH_GL11:
3316                 break;
3317         }
3318 }
3319
3320 #define SKINFRAME_HASH 1024
3321
3322 typedef struct
3323 {
3324         int loadsequence; // incremented each level change
3325         memexpandablearray_t array;
3326         skinframe_t *hash[SKINFRAME_HASH];
3327 }
3328 r_skinframe_t;
3329 r_skinframe_t r_skinframe;
3330
3331 void R_SkinFrame_PrepareForPurge(void)
3332 {
3333         r_skinframe.loadsequence++;
3334         // wrap it without hitting zero
3335         if (r_skinframe.loadsequence >= 200)
3336                 r_skinframe.loadsequence = 1;
3337 }
3338
3339 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3340 {
3341         if (!skinframe)
3342                 return;
3343         // mark the skinframe as used for the purging code
3344         skinframe->loadsequence = r_skinframe.loadsequence;
3345 }
3346
3347 void R_SkinFrame_Purge(void)
3348 {
3349         int i;
3350         skinframe_t *s;
3351         for (i = 0;i < SKINFRAME_HASH;i++)
3352         {
3353                 for (s = r_skinframe.hash[i];s;s = s->next)
3354                 {
3355                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3356                         {
3357                                 if (s->merged == s->base)
3358                                         s->merged = NULL;
3359                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3360                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3361                                 R_PurgeTexture(s->merged);s->merged = NULL;
3362                                 R_PurgeTexture(s->base  );s->base   = NULL;
3363                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3364                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3365                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3366                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3367                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3368                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3369                                 s->loadsequence = 0;
3370                         }
3371                 }
3372         }
3373 }
3374
3375 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3376         skinframe_t *item;
3377         char basename[MAX_QPATH];
3378
3379         Image_StripImageExtension(name, basename, sizeof(basename));
3380
3381         if( last == NULL ) {
3382                 int hashindex;
3383                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3384                 item = r_skinframe.hash[hashindex];
3385         } else {
3386                 item = last->next;
3387         }
3388
3389         // linearly search through the hash bucket
3390         for( ; item ; item = item->next ) {
3391                 if( !strcmp( item->basename, basename ) ) {
3392                         return item;
3393                 }
3394         }
3395         return NULL;
3396 }
3397
3398 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3399 {
3400         skinframe_t *item;
3401         int hashindex;
3402         char basename[MAX_QPATH];
3403
3404         Image_StripImageExtension(name, basename, sizeof(basename));
3405
3406         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3407         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3408                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3409                         break;
3410
3411         if (!item) {
3412                 rtexture_t *dyntexture;
3413                 // check whether its a dynamic texture
3414                 dyntexture = CL_GetDynTexture( basename );
3415                 if (!add && !dyntexture)
3416                         return NULL;
3417                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3418                 memset(item, 0, sizeof(*item));
3419                 strlcpy(item->basename, basename, sizeof(item->basename));
3420                 item->base = dyntexture; // either NULL or dyntexture handle
3421                 item->textureflags = textureflags;
3422                 item->comparewidth = comparewidth;
3423                 item->compareheight = compareheight;
3424                 item->comparecrc = comparecrc;
3425                 item->next = r_skinframe.hash[hashindex];
3426                 r_skinframe.hash[hashindex] = item;
3427         }
3428         else if( item->base == NULL )
3429         {
3430                 rtexture_t *dyntexture;
3431                 // check whether its a dynamic texture
3432                 // 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]
3433                 dyntexture = CL_GetDynTexture( basename );
3434                 item->base = dyntexture; // either NULL or dyntexture handle
3435         }
3436
3437         R_SkinFrame_MarkUsed(item);
3438         return item;
3439 }
3440
3441 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3442         { \
3443                 unsigned long long avgcolor[5], wsum; \
3444                 int pix, comp, w; \
3445                 avgcolor[0] = 0; \
3446                 avgcolor[1] = 0; \
3447                 avgcolor[2] = 0; \
3448                 avgcolor[3] = 0; \
3449                 avgcolor[4] = 0; \
3450                 wsum = 0; \
3451                 for(pix = 0; pix < cnt; ++pix) \
3452                 { \
3453                         w = 0; \
3454                         for(comp = 0; comp < 3; ++comp) \
3455                                 w += getpixel; \
3456                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3457                         { \
3458                                 ++wsum; \
3459                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3460                                 w = getpixel; \
3461                                 for(comp = 0; comp < 3; ++comp) \
3462                                         avgcolor[comp] += getpixel * w; \
3463                                 avgcolor[3] += w; \
3464                         } \
3465                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3466                         avgcolor[4] += getpixel; \
3467                 } \
3468                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3469                         avgcolor[3] = 1; \
3470                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3471                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3472                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3473                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3474         }
3475
3476 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3477 {
3478         int j;
3479         unsigned char *pixels;
3480         unsigned char *bumppixels;
3481         unsigned char *basepixels = NULL;
3482         int basepixels_width;
3483         int basepixels_height;
3484         skinframe_t *skinframe;
3485
3486         if (cls.state == ca_dedicated)
3487                 return NULL;
3488
3489         // return an existing skinframe if already loaded
3490         // if loading of the first image fails, don't make a new skinframe as it
3491         // would cause all future lookups of this to be missing
3492         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3493         if (skinframe && skinframe->base)
3494                 return skinframe;
3495
3496         basepixels = loadimagepixelsbgra(name, complain, true);
3497         if (basepixels == NULL)
3498                 return NULL;
3499
3500         if (developer_loading.integer)
3501                 Con_Printf("loading skin \"%s\"\n", name);
3502
3503         // we've got some pixels to store, so really allocate this new texture now
3504         if (!skinframe)
3505                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3506         skinframe->stain = NULL;
3507         skinframe->merged = NULL;
3508         skinframe->base = r_texture_notexture;
3509         skinframe->pants = NULL;
3510         skinframe->shirt = NULL;
3511         skinframe->nmap = r_texture_blanknormalmap;
3512         skinframe->gloss = NULL;
3513         skinframe->glow = NULL;
3514         skinframe->fog = NULL;
3515         skinframe->hasalpha = false;
3516
3517         basepixels_width = image_width;
3518         basepixels_height = image_height;
3519         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);
3520
3521         if (textureflags & TEXF_ALPHA)
3522         {
3523                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3524                 {
3525                         if (basepixels[j] < 255)
3526                         {
3527                                 skinframe->hasalpha = true;
3528                                 break;
3529                         }
3530                 }
3531                 if (r_loadfog && skinframe->hasalpha)
3532                 {
3533                         // has transparent pixels
3534                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3535                         for (j = 0;j < image_width * image_height * 4;j += 4)
3536                         {
3537                                 pixels[j+0] = 255;
3538                                 pixels[j+1] = 255;
3539                                 pixels[j+2] = 255;
3540                                 pixels[j+3] = basepixels[j+3];
3541                         }
3542                         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);
3543                         Mem_Free(pixels);
3544                 }
3545         }
3546
3547         R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3548         //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]);
3549
3550         // _norm is the name used by tenebrae and has been adopted as standard
3551         if (r_loadnormalmap)
3552         {
3553                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
3554                 {
3555                         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);
3556                         Mem_Free(pixels);
3557                         pixels = NULL;
3558                 }
3559                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
3560                 {
3561                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3562                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3563                         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);
3564                         Mem_Free(pixels);
3565                         Mem_Free(bumppixels);
3566                 }
3567                 else if (r_shadow_bumpscale_basetexture.value > 0)
3568                 {
3569                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3570                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3571                         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);
3572                         Mem_Free(pixels);
3573                 }
3574         }
3575         // _luma is supported for tenebrae compatibility
3576         // (I think it's a very stupid name, but oh well)
3577         // _glow is the preferred name
3578         if ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))) {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);Mem_Free(pixels);pixels = NULL;}
3579         if (r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false))) {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);Mem_Free(pixels);pixels = NULL;}
3580         if ((pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false))) {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);Mem_Free(pixels);pixels = NULL;}
3581         if ((pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false))) {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);Mem_Free(pixels);pixels = NULL;}
3582
3583         if (basepixels)
3584                 Mem_Free(basepixels);
3585
3586         return skinframe;
3587 }
3588
3589 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3590 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3591 {
3592         int i;
3593         unsigned char *temp1, *temp2;
3594         skinframe_t *skinframe;
3595
3596         if (cls.state == ca_dedicated)
3597                 return NULL;
3598
3599         // if already loaded just return it, otherwise make a new skinframe
3600         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3601         if (skinframe && skinframe->base)
3602                 return skinframe;
3603
3604         skinframe->stain = NULL;
3605         skinframe->merged = NULL;
3606         skinframe->base = r_texture_notexture;
3607         skinframe->pants = NULL;
3608         skinframe->shirt = NULL;
3609         skinframe->nmap = r_texture_blanknormalmap;
3610         skinframe->gloss = NULL;
3611         skinframe->glow = NULL;
3612         skinframe->fog = NULL;
3613         skinframe->hasalpha = false;
3614
3615         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3616         if (!skindata)
3617                 return NULL;
3618
3619         if (developer_loading.integer)
3620                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3621
3622         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3623         {
3624                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3625                 temp2 = temp1 + width * height * 4;
3626                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3627                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3628                 Mem_Free(temp1);
3629         }
3630         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
3631         if (textureflags & TEXF_ALPHA)
3632         {
3633                 for (i = 3;i < width * height * 4;i += 4)
3634                 {
3635                         if (skindata[i] < 255)
3636                         {
3637                                 skinframe->hasalpha = true;
3638                                 break;
3639                         }
3640                 }
3641                 if (r_loadfog && skinframe->hasalpha)
3642                 {
3643                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3644                         memcpy(fogpixels, skindata, width * height * 4);
3645                         for (i = 0;i < width * height * 4;i += 4)
3646                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3647                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
3648                         Mem_Free(fogpixels);
3649                 }
3650         }
3651
3652         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3653         //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]);
3654
3655         return skinframe;
3656 }
3657
3658 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3659 {
3660         int i;
3661         int featuresmask;
3662         skinframe_t *skinframe;
3663
3664         if (cls.state == ca_dedicated)
3665                 return NULL;
3666
3667         // if already loaded just return it, otherwise make a new skinframe
3668         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3669         if (skinframe && skinframe->base)
3670                 return skinframe;
3671
3672         skinframe->stain = NULL;
3673         skinframe->merged = NULL;
3674         skinframe->base = r_texture_notexture;
3675         skinframe->pants = NULL;
3676         skinframe->shirt = NULL;
3677         skinframe->nmap = r_texture_blanknormalmap;
3678         skinframe->gloss = NULL;
3679         skinframe->glow = NULL;
3680         skinframe->fog = NULL;
3681         skinframe->hasalpha = false;
3682
3683         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3684         if (!skindata)
3685                 return NULL;
3686
3687         if (developer_loading.integer)
3688                 Con_Printf("loading quake skin \"%s\"\n", name);
3689
3690         // 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)
3691         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
3692         memcpy(skinframe->qpixels, skindata, width*height);
3693         skinframe->qwidth = width;
3694         skinframe->qheight = height;
3695
3696         featuresmask = 0;
3697         for (i = 0;i < width * height;i++)
3698                 featuresmask |= palette_featureflags[skindata[i]];
3699
3700         skinframe->hasalpha = false;
3701         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3702         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3703         skinframe->qgeneratemerged = true;
3704         skinframe->qgeneratebase = skinframe->qhascolormapping;
3705         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3706
3707         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3708         //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]);
3709
3710         return skinframe;
3711 }
3712
3713 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3714 {
3715         int width;
3716         int height;
3717         unsigned char *skindata;
3718
3719         if (!skinframe->qpixels)
3720                 return;
3721
3722         if (!skinframe->qhascolormapping)
3723                 colormapped = false;
3724
3725         if (colormapped)
3726         {
3727                 if (!skinframe->qgeneratebase)
3728                         return;
3729         }
3730         else
3731         {
3732                 if (!skinframe->qgeneratemerged)
3733                         return;
3734         }
3735
3736         width = skinframe->qwidth;
3737         height = skinframe->qheight;
3738         skindata = skinframe->qpixels;
3739
3740         if (skinframe->qgeneratenmap)
3741         {
3742                 unsigned char *temp1, *temp2;
3743                 skinframe->qgeneratenmap = false;
3744                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3745                 temp2 = temp1 + width * height * 4;
3746                 // use either a custom palette or the quake palette
3747                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3748                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3749                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3750                 Mem_Free(temp1);
3751         }
3752
3753         if (skinframe->qgenerateglow)
3754         {
3755                 skinframe->qgenerateglow = false;
3756                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
3757         }
3758
3759         if (colormapped)
3760         {
3761                 skinframe->qgeneratebase = false;
3762                 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);
3763                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
3764                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
3765         }
3766         else
3767         {
3768                 skinframe->qgeneratemerged = false;
3769                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3770         }
3771
3772         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3773         {
3774                 Mem_Free(skinframe->qpixels);
3775                 skinframe->qpixels = NULL;
3776         }
3777 }
3778
3779 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)
3780 {
3781         int i;
3782         skinframe_t *skinframe;
3783
3784         if (cls.state == ca_dedicated)
3785                 return NULL;
3786
3787         // if already loaded just return it, otherwise make a new skinframe
3788         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3789         if (skinframe && skinframe->base)
3790                 return skinframe;
3791
3792         skinframe->stain = NULL;
3793         skinframe->merged = NULL;
3794         skinframe->base = r_texture_notexture;
3795         skinframe->pants = NULL;
3796         skinframe->shirt = NULL;
3797         skinframe->nmap = r_texture_blanknormalmap;
3798         skinframe->gloss = NULL;
3799         skinframe->glow = NULL;
3800         skinframe->fog = NULL;
3801         skinframe->hasalpha = false;
3802
3803         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3804         if (!skindata)
3805                 return NULL;
3806
3807         if (developer_loading.integer)
3808                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3809
3810         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3811         if (textureflags & TEXF_ALPHA)
3812         {
3813                 for (i = 0;i < width * height;i++)
3814                 {
3815                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3816                         {
3817                                 skinframe->hasalpha = true;
3818                                 break;
3819                         }
3820                 }
3821                 if (r_loadfog && skinframe->hasalpha)
3822                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3823         }
3824
3825         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3826         //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]);
3827
3828         return skinframe;
3829 }
3830
3831 skinframe_t *R_SkinFrame_LoadMissing(void)
3832 {
3833         skinframe_t *skinframe;
3834
3835         if (cls.state == ca_dedicated)
3836                 return NULL;
3837
3838         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3839         skinframe->stain = NULL;
3840         skinframe->merged = NULL;
3841         skinframe->base = r_texture_notexture;
3842         skinframe->pants = NULL;
3843         skinframe->shirt = NULL;
3844         skinframe->nmap = r_texture_blanknormalmap;
3845         skinframe->gloss = NULL;
3846         skinframe->glow = NULL;
3847         skinframe->fog = NULL;
3848         skinframe->hasalpha = false;
3849
3850         skinframe->avgcolor[0] = rand() / RAND_MAX;
3851         skinframe->avgcolor[1] = rand() / RAND_MAX;
3852         skinframe->avgcolor[2] = rand() / RAND_MAX;
3853         skinframe->avgcolor[3] = 1;
3854
3855         return skinframe;
3856 }
3857
3858 void R_Main_FreeViewCache(void)
3859 {
3860         if (r_refdef.viewcache.entityvisible)
3861                 Mem_Free(r_refdef.viewcache.entityvisible);
3862         if (r_refdef.viewcache.world_pvsbits)
3863                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3864         if (r_refdef.viewcache.world_leafvisible)
3865                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3866         if (r_refdef.viewcache.world_surfacevisible)
3867                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3868         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3869 }
3870
3871 void R_Main_ResizeViewCache(void)
3872 {
3873         int numentities = r_refdef.scene.numentities;
3874         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3875         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3876         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3877         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3878         if (r_refdef.viewcache.maxentities < numentities)
3879         {
3880                 r_refdef.viewcache.maxentities = numentities;
3881                 if (r_refdef.viewcache.entityvisible)
3882                         Mem_Free(r_refdef.viewcache.entityvisible);
3883                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3884         }
3885         if (r_refdef.viewcache.world_numclusters != numclusters)
3886         {
3887                 r_refdef.viewcache.world_numclusters = numclusters;
3888                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3889                 if (r_refdef.viewcache.world_pvsbits)
3890                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3891                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3892         }
3893         if (r_refdef.viewcache.world_numleafs != numleafs)
3894         {
3895                 r_refdef.viewcache.world_numleafs = numleafs;
3896                 if (r_refdef.viewcache.world_leafvisible)
3897                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3898                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3899         }
3900         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3901         {
3902                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3903                 if (r_refdef.viewcache.world_surfacevisible)
3904                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3905                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3906         }
3907 }
3908
3909 extern rtexture_t *loadingscreentexture;
3910 void gl_main_start(void)
3911 {
3912         loadingscreentexture = NULL;
3913         r_texture_blanknormalmap = NULL;
3914         r_texture_white = NULL;
3915         r_texture_grey128 = NULL;
3916         r_texture_black = NULL;
3917         r_texture_whitecube = NULL;
3918         r_texture_normalizationcube = NULL;
3919         r_texture_fogattenuation = NULL;
3920         r_texture_gammaramps = NULL;
3921
3922         switch(vid.renderpath)
3923         {
3924         case RENDERPATH_GL20:
3925         case RENDERPATH_CGGL:
3926                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3927                 Cvar_SetValueQuick(&gl_combine, 1);
3928                 Cvar_SetValueQuick(&r_glsl, 1);
3929                 r_loadnormalmap = true;
3930                 r_loadgloss = true;
3931                 r_loadfog = false;
3932                 break;
3933         case RENDERPATH_GL13:
3934                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3935                 Cvar_SetValueQuick(&gl_combine, 1);
3936                 Cvar_SetValueQuick(&r_glsl, 0);
3937                 r_loadnormalmap = false;
3938                 r_loadgloss = false;
3939                 r_loadfog = true;
3940                 break;
3941         case RENDERPATH_GL11:
3942                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3943                 Cvar_SetValueQuick(&gl_combine, 0);
3944                 Cvar_SetValueQuick(&r_glsl, 0);
3945                 r_loadnormalmap = false;
3946                 r_loadgloss = false;
3947                 r_loadfog = true;
3948                 break;
3949         }
3950
3951         R_AnimCache_Free();
3952         R_FrameData_Reset();
3953
3954         r_numqueries = 0;
3955         r_maxqueries = 0;
3956         memset(r_queries, 0, sizeof(r_queries));
3957
3958         r_qwskincache = NULL;
3959         r_qwskincache_size = 0;
3960
3961         // set up r_skinframe loading system for textures
3962         memset(&r_skinframe, 0, sizeof(r_skinframe));
3963         r_skinframe.loadsequence = 1;
3964         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3965
3966         r_main_texturepool = R_AllocTexturePool();
3967         R_BuildBlankTextures();
3968         R_BuildNoTexture();
3969         if (vid.support.arb_texture_cube_map)
3970         {
3971                 R_BuildWhiteCube();
3972                 R_BuildNormalizationCube();
3973         }
3974         r_texture_fogattenuation = NULL;
3975         r_texture_gammaramps = NULL;
3976         //r_texture_fogintensity = NULL;
3977         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3978         memset(&r_waterstate, 0, sizeof(r_waterstate));
3979         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3980         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3981 #ifdef SUPPORTCG
3982         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
3983         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
3984 #endif
3985         memset(&r_svbsp, 0, sizeof (r_svbsp));
3986
3987         r_refdef.fogmasktable_density = 0;
3988 }
3989
3990 void gl_main_shutdown(void)
3991 {
3992         R_AnimCache_Free();
3993         R_FrameData_Reset();
3994
3995         R_Main_FreeViewCache();
3996
3997         if (r_maxqueries)
3998                 qglDeleteQueriesARB(r_maxqueries, r_queries);
3999
4000         r_numqueries = 0;
4001         r_maxqueries = 0;
4002         memset(r_queries, 0, sizeof(r_queries));
4003
4004         r_qwskincache = NULL;
4005         r_qwskincache_size = 0;
4006
4007         // clear out the r_skinframe state
4008         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4009         memset(&r_skinframe, 0, sizeof(r_skinframe));
4010
4011         if (r_svbsp.nodes)
4012                 Mem_Free(r_svbsp.nodes);
4013         memset(&r_svbsp, 0, sizeof (r_svbsp));
4014         R_FreeTexturePool(&r_main_texturepool);
4015         loadingscreentexture = NULL;
4016         r_texture_blanknormalmap = NULL;
4017         r_texture_white = NULL;
4018         r_texture_grey128 = NULL;
4019         r_texture_black = NULL;
4020         r_texture_whitecube = NULL;
4021         r_texture_normalizationcube = NULL;
4022         r_texture_fogattenuation = NULL;
4023         r_texture_gammaramps = NULL;
4024         //r_texture_fogintensity = NULL;
4025         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4026         memset(&r_waterstate, 0, sizeof(r_waterstate));
4027         R_GLSL_Restart_f();
4028 }
4029
4030 extern void CL_ParseEntityLump(char *entitystring);
4031 void gl_main_newmap(void)
4032 {
4033         // FIXME: move this code to client
4034         int l;
4035         char *entities, entname[MAX_QPATH];
4036         if (r_qwskincache)
4037                 Mem_Free(r_qwskincache);
4038         r_qwskincache = NULL;
4039         r_qwskincache_size = 0;
4040         if (cl.worldmodel)
4041         {
4042                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
4043                 l = (int)strlen(entname) - 4;
4044                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
4045                 {
4046                         memcpy(entname + l, ".ent", 5);
4047                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4048                         {
4049                                 CL_ParseEntityLump(entities);
4050                                 Mem_Free(entities);
4051                                 return;
4052                         }
4053                 }
4054                 if (cl.worldmodel->brush.entities)
4055                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4056         }
4057         R_Main_FreeViewCache();
4058
4059         R_FrameData_Reset();
4060 }
4061
4062 void GL_Main_Init(void)
4063 {
4064         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4065
4066         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4067         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4068         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4069         if (gamemode == GAME_NEHAHRA)
4070         {
4071                 Cvar_RegisterVariable (&gl_fogenable);
4072                 Cvar_RegisterVariable (&gl_fogdensity);
4073                 Cvar_RegisterVariable (&gl_fogred);
4074                 Cvar_RegisterVariable (&gl_foggreen);
4075                 Cvar_RegisterVariable (&gl_fogblue);
4076                 Cvar_RegisterVariable (&gl_fogstart);
4077                 Cvar_RegisterVariable (&gl_fogend);
4078                 Cvar_RegisterVariable (&gl_skyclip);
4079         }
4080         Cvar_RegisterVariable(&r_motionblur);
4081         Cvar_RegisterVariable(&r_motionblur_maxblur);
4082         Cvar_RegisterVariable(&r_motionblur_bmin);
4083         Cvar_RegisterVariable(&r_motionblur_vmin);
4084         Cvar_RegisterVariable(&r_motionblur_vmax);
4085         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4086         Cvar_RegisterVariable(&r_motionblur_randomize);
4087         Cvar_RegisterVariable(&r_damageblur);
4088         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4089         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4090         Cvar_RegisterVariable(&r_equalize_entities_by);
4091         Cvar_RegisterVariable(&r_equalize_entities_to);
4092         Cvar_RegisterVariable(&r_depthfirst);
4093         Cvar_RegisterVariable(&r_useinfinitefarclip);
4094         Cvar_RegisterVariable(&r_farclip_base);
4095         Cvar_RegisterVariable(&r_farclip_world);
4096         Cvar_RegisterVariable(&r_nearclip);
4097         Cvar_RegisterVariable(&r_showbboxes);
4098         Cvar_RegisterVariable(&r_showsurfaces);
4099         Cvar_RegisterVariable(&r_showtris);
4100         Cvar_RegisterVariable(&r_shownormals);
4101         Cvar_RegisterVariable(&r_showlighting);
4102         Cvar_RegisterVariable(&r_showshadowvolumes);
4103         Cvar_RegisterVariable(&r_showcollisionbrushes);
4104         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4105         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4106         Cvar_RegisterVariable(&r_showdisabledepthtest);
4107         Cvar_RegisterVariable(&r_drawportals);
4108         Cvar_RegisterVariable(&r_drawentities);
4109         Cvar_RegisterVariable(&r_cullentities_trace);
4110         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4111         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4112         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4113         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4114         Cvar_RegisterVariable(&r_drawviewmodel);
4115         Cvar_RegisterVariable(&r_speeds);
4116         Cvar_RegisterVariable(&r_fullbrights);
4117         Cvar_RegisterVariable(&r_wateralpha);
4118         Cvar_RegisterVariable(&r_dynamic);
4119         Cvar_RegisterVariable(&r_fullbright);
4120         Cvar_RegisterVariable(&r_shadows);
4121         Cvar_RegisterVariable(&r_shadows_darken);
4122         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4123         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4124         Cvar_RegisterVariable(&r_shadows_throwdistance);
4125         Cvar_RegisterVariable(&r_shadows_throwdirection);
4126         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4127         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4128         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4129         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4130         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4131         Cvar_RegisterVariable(&r_fog_exp2);
4132         Cvar_RegisterVariable(&r_drawfog);
4133         Cvar_RegisterVariable(&r_transparentdepthmasking);
4134         Cvar_RegisterVariable(&r_textureunits);
4135         Cvar_RegisterVariable(&gl_combine);
4136         Cvar_RegisterVariable(&r_glsl);
4137         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4138         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4139         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4140         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4141         Cvar_RegisterVariable(&r_glsl_postprocess);
4142         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4143         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4144         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4145         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4146         Cvar_RegisterVariable(&r_water);
4147         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4148         Cvar_RegisterVariable(&r_water_clippingplanebias);
4149         Cvar_RegisterVariable(&r_water_refractdistort);
4150         Cvar_RegisterVariable(&r_water_reflectdistort);
4151         Cvar_RegisterVariable(&r_lerpsprites);
4152         Cvar_RegisterVariable(&r_lerpmodels);
4153         Cvar_RegisterVariable(&r_lerplightstyles);
4154         Cvar_RegisterVariable(&r_waterscroll);
4155         Cvar_RegisterVariable(&r_bloom);
4156         Cvar_RegisterVariable(&r_bloom_colorscale);
4157         Cvar_RegisterVariable(&r_bloom_brighten);
4158         Cvar_RegisterVariable(&r_bloom_blur);
4159         Cvar_RegisterVariable(&r_bloom_resolution);
4160         Cvar_RegisterVariable(&r_bloom_colorexponent);
4161         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4162         Cvar_RegisterVariable(&r_hdr);
4163         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4164         Cvar_RegisterVariable(&r_hdr_glowintensity);
4165         Cvar_RegisterVariable(&r_hdr_range);
4166         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4167         Cvar_RegisterVariable(&developer_texturelogging);
4168         Cvar_RegisterVariable(&gl_lightmaps);
4169         Cvar_RegisterVariable(&r_test);
4170         Cvar_RegisterVariable(&r_batchmode);
4171         Cvar_RegisterVariable(&r_glsl_saturation);
4172         Cvar_RegisterVariable(&r_framedatasize);
4173         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4174                 Cvar_SetValue("r_fullbrights", 0);
4175         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
4176
4177         Cvar_RegisterVariable(&r_track_sprites);
4178         Cvar_RegisterVariable(&r_track_sprites_flags);
4179         Cvar_RegisterVariable(&r_track_sprites_scalew);
4180         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4181 }
4182
4183 extern void R_Textures_Init(void);
4184 extern void GL_Draw_Init(void);
4185 extern void GL_Main_Init(void);
4186 extern void R_Shadow_Init(void);
4187 extern void R_Sky_Init(void);
4188 extern void GL_Surf_Init(void);
4189 extern void R_Particles_Init(void);
4190 extern void R_Explosion_Init(void);
4191 extern void gl_backend_init(void);
4192 extern void Sbar_Init(void);
4193 extern void R_LightningBeams_Init(void);
4194 extern void Mod_RenderInit(void);
4195 extern void Font_Init(void);
4196
4197 void Render_Init(void)
4198 {
4199         gl_backend_init();
4200         R_Textures_Init();
4201         GL_Main_Init();
4202         Font_Init();
4203         GL_Draw_Init();
4204         R_Shadow_Init();
4205         R_Sky_Init();
4206         GL_Surf_Init();
4207         Sbar_Init();
4208         R_Particles_Init();
4209         R_Explosion_Init();
4210         R_LightningBeams_Init();
4211         Mod_RenderInit();
4212 }
4213
4214 /*
4215 ===============
4216 GL_Init
4217 ===============
4218 */
4219 extern char *ENGINE_EXTENSIONS;
4220 void GL_Init (void)
4221 {
4222         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4223         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4224         gl_version = (const char *)qglGetString(GL_VERSION);
4225         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4226
4227         if (!gl_extensions)
4228                 gl_extensions = "";
4229         if (!gl_platformextensions)
4230                 gl_platformextensions = "";
4231
4232         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4233         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4234         Con_Printf("GL_VERSION: %s\n", gl_version);
4235         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4236         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4237
4238         VID_CheckExtensions();
4239
4240         // LordHavoc: report supported extensions
4241         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4242
4243         // clear to black (loading plaque will be seen over this)
4244         CHECKGLERROR
4245         qglClearColor(0,0,0,1);CHECKGLERROR
4246         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
4247 }
4248
4249 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4250 {
4251         int i;
4252         mplane_t *p;
4253         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4254         {
4255                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4256                 if (i == 4)
4257                         continue;
4258                 p = r_refdef.view.frustum + i;
4259                 switch(p->signbits)
4260                 {
4261                 default:
4262                 case 0:
4263                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4264                                 return true;
4265                         break;
4266                 case 1:
4267                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4268                                 return true;
4269                         break;
4270                 case 2:
4271                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4272                                 return true;
4273                         break;
4274                 case 3:
4275                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4276                                 return true;
4277                         break;
4278                 case 4:
4279                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4280                                 return true;
4281                         break;
4282                 case 5:
4283                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4284                                 return true;
4285                         break;
4286                 case 6:
4287                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4288                                 return true;
4289                         break;
4290                 case 7:
4291                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4292                                 return true;
4293                         break;
4294                 }
4295         }
4296         return false;
4297 }
4298
4299 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4300 {
4301         int i;
4302         const mplane_t *p;
4303         for (i = 0;i < numplanes;i++)
4304         {
4305                 p = planes + i;
4306                 switch(p->signbits)
4307                 {
4308                 default:
4309                 case 0:
4310                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4311                                 return true;
4312                         break;
4313                 case 1:
4314                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4315                                 return true;
4316                         break;
4317                 case 2:
4318                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4319                                 return true;
4320                         break;
4321                 case 3:
4322                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4323                                 return true;
4324                         break;
4325                 case 4:
4326                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4327                                 return true;
4328                         break;
4329                 case 5:
4330                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4331                                 return true;
4332                         break;
4333                 case 6:
4334                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4335                                 return true;
4336                         break;
4337                 case 7:
4338                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4339                                 return true;
4340                         break;
4341                 }
4342         }
4343         return false;
4344 }
4345
4346 //==================================================================================
4347
4348 // LordHavoc: this stores temporary data used within the same frame
4349
4350 qboolean r_framedata_failed;
4351 static size_t r_framedata_size;
4352 static size_t r_framedata_current;
4353 static void *r_framedata_base;
4354
4355 void R_FrameData_Reset(void)
4356 {
4357         if (r_framedata_base);
4358                 Mem_Free(r_framedata_base);
4359         r_framedata_base = NULL;
4360         r_framedata_size = 0;
4361         r_framedata_current = 0;
4362         r_framedata_failed = false;
4363 }
4364
4365 void R_FrameData_NewFrame(void)
4366 {
4367         size_t wantedsize;
4368         if (r_framedata_failed)
4369                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
4370         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4371         wantedsize = bound(65536, wantedsize, 128*1024*1024);
4372         if (r_framedata_size != wantedsize)
4373         {
4374                 r_framedata_size = wantedsize;
4375                 if (r_framedata_base);
4376                         Mem_Free(r_framedata_base);
4377                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
4378         }
4379         r_framedata_current = 0;
4380         r_framedata_failed = false;
4381 }
4382
4383 void *R_FrameData_Alloc(size_t size)
4384 {
4385         void *data;
4386
4387         // align to 16 byte boundary
4388         size = (size + 15) & ~15;
4389         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
4390         r_framedata_current += size;
4391
4392         // check overflow
4393         if (r_framedata_current > r_framedata_size)
4394                 r_framedata_failed = true;
4395
4396         // return NULL on everything after a failure
4397         if (r_framedata_failed)
4398                 return NULL;
4399
4400         return data;
4401 }
4402
4403 void *R_FrameData_Store(size_t size, void *data)
4404 {
4405         void *d = R_FrameData_Alloc(size);
4406         if (d)
4407                 memcpy(d, data, size);
4408         return d;
4409 }
4410
4411 //==================================================================================
4412
4413 // LordHavoc: animcache originally written by Echon, rewritten since then
4414
4415 /**
4416  * Animation cache prevents re-generating mesh data for an animated model
4417  * multiple times in one frame for lighting, shadowing, reflections, etc.
4418  */
4419
4420 void R_AnimCache_Free(void)
4421 {
4422 }
4423
4424 void R_AnimCache_ClearCache(void)
4425 {
4426         int i;
4427         entity_render_t *ent;
4428
4429         for (i = 0;i < r_refdef.scene.numentities;i++)
4430         {
4431                 ent = r_refdef.scene.entities[i];
4432                 ent->animcache_vertex3f = NULL;
4433                 ent->animcache_normal3f = NULL;
4434                 ent->animcache_svector3f = NULL;
4435                 ent->animcache_tvector3f = NULL;
4436         }
4437 }
4438
4439 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4440 {
4441         dp_model_t *model = ent->model;
4442         int numvertices;
4443         // see if it's already cached this frame
4444         if (ent->animcache_vertex3f)
4445         {
4446                 // add normals/tangents if needed
4447                 if (wantnormals || wanttangents)
4448                 {
4449                         if (ent->animcache_normal3f)
4450                                 wantnormals = false;
4451                         if (ent->animcache_svector3f)
4452                                 wanttangents = false;
4453                         if (wantnormals || wanttangents)
4454                         {
4455                                 numvertices = model->surfmesh.num_vertices;
4456                                 if (wantnormals)
4457                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4458                                 if (wanttangents)
4459                                 {
4460                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4461                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4462                                 }
4463                                 if (!r_framedata_failed)
4464                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4465                         }
4466                 }
4467         }
4468         else
4469         {
4470                 // see if this ent is worth caching
4471                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4472                         return false;
4473                 // get some memory for this entity and generate mesh data
4474                 numvertices = model->surfmesh.num_vertices;
4475                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4476                 if (wantnormals)
4477                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4478                 if (wanttangents)
4479                 {
4480                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4481                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4482                 }
4483                 if (!r_framedata_failed)
4484                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4485         }
4486         return !r_framedata_failed;
4487 }
4488
4489 void R_AnimCache_CacheVisibleEntities(void)
4490 {
4491         int i;
4492         qboolean wantnormals = !r_showsurfaces.integer;
4493         qboolean wanttangents = !r_showsurfaces.integer;
4494
4495         switch(vid.renderpath)
4496         {
4497         case RENDERPATH_GL20:
4498         case RENDERPATH_CGGL:
4499                 break;
4500         case RENDERPATH_GL13:
4501         case RENDERPATH_GL11:
4502                 wanttangents = false;
4503                 break;
4504         }
4505
4506         // TODO: thread this
4507         // NOTE: R_PrepareRTLights() also caches entities
4508
4509         for (i = 0;i < r_refdef.scene.numentities;i++)
4510                 if (r_refdef.viewcache.entityvisible[i])
4511                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4512
4513         if (r_shadows.integer)
4514                 for (i = 0;i < r_refdef.scene.numentities;i++)
4515                         if (!r_refdef.viewcache.entityvisible[i])
4516                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
4517 }
4518
4519 //==================================================================================
4520
4521 static void R_View_UpdateEntityLighting (void)
4522 {
4523         int i;
4524         entity_render_t *ent;
4525         vec3_t tempdiffusenormal, avg;
4526         vec_t f, fa, fd, fdd;
4527
4528         for (i = 0;i < r_refdef.scene.numentities;i++)
4529         {
4530                 ent = r_refdef.scene.entities[i];
4531
4532                 // skip unseen models
4533                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
4534                         continue;
4535
4536                 // skip bsp models
4537                 if (ent->model && ent->model->brush.num_leafs)
4538                 {
4539                         // TODO: use modellight for r_ambient settings on world?
4540                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4541                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4542                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4543                         continue;
4544                 }
4545
4546                 // fetch the lighting from the worldmodel data
4547                 VectorClear(ent->modellight_ambient);
4548                 VectorClear(ent->modellight_diffuse);
4549                 VectorClear(tempdiffusenormal);
4550                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4551                 {
4552                         vec3_t org;
4553                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4554                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
4555                         if(ent->flags & RENDER_EQUALIZE)
4556                         {
4557                                 // first fix up ambient lighting...
4558                                 if(r_equalize_entities_minambient.value > 0)
4559                                 {
4560                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4561                                         if(fd > 0)
4562                                         {
4563                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4564                                                 if(fa < r_equalize_entities_minambient.value * fd)
4565                                                 {
4566                                                         // solve:
4567                                                         //   fa'/fd' = minambient
4568                                                         //   fa'+0.25*fd' = fa+0.25*fd
4569                                                         //   ...
4570                                                         //   fa' = fd' * minambient
4571                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4572                                                         //   ...
4573                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4574                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4575                                                         //   ...
4576                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4577                                                         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
4578                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4579                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4580                                                 }
4581                                         }
4582                                 }
4583
4584                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4585                                 {
4586                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
4587                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
4588                                         if(f > 0)
4589                                         {
4590                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
4591                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
4592                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4593                                         }
4594                                 }
4595                         }
4596                 }
4597                 else // highly rare
4598                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4599
4600                 // move the light direction into modelspace coordinates for lighting code
4601                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4602                 if(VectorLength2(ent->modellight_lightdir) == 0)
4603                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4604                 VectorNormalize(ent->modellight_lightdir);
4605         }
4606 }
4607
4608 #define MAX_LINEOFSIGHTTRACES 64
4609
4610 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4611 {
4612         int i;
4613         vec3_t boxmins, boxmaxs;
4614         vec3_t start;
4615         vec3_t end;
4616         dp_model_t *model = r_refdef.scene.worldmodel;
4617
4618         if (!model || !model->brush.TraceLineOfSight)
4619                 return true;
4620
4621         // expand the box a little
4622         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4623         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4624         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4625         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4626         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4627         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4628
4629         // try center
4630         VectorCopy(eye, start);
4631         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4632         if (model->brush.TraceLineOfSight(model, start, end))
4633                 return true;
4634
4635         // try various random positions
4636         for (i = 0;i < numsamples;i++)
4637         {
4638                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4639                 if (model->brush.TraceLineOfSight(model, start, end))
4640                         return true;
4641         }
4642
4643         return false;
4644 }
4645
4646
4647 static void R_View_UpdateEntityVisible (void)
4648 {
4649         int i;
4650         int renderimask;
4651         int samples;
4652         entity_render_t *ent;
4653
4654         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
4655         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4656         {
4657                 // worldmodel can check visibility
4658                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4659                 for (i = 0;i < r_refdef.scene.numentities;i++)
4660                 {
4661                         ent = r_refdef.scene.entities[i];
4662                         if (!(ent->flags & renderimask))
4663                         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)))
4664                         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))
4665                                 r_refdef.viewcache.entityvisible[i] = true;
4666                 }
4667                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
4668                 {
4669                         for (i = 0;i < r_refdef.scene.numentities;i++)
4670                         {
4671                                 ent = r_refdef.scene.entities[i];
4672                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4673                                 {
4674                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4675                                         if (samples < 0)
4676                                                 continue; // temp entities do pvs only
4677                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4678                                                 ent->last_trace_visibility = realtime;
4679                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4680                                                 r_refdef.viewcache.entityvisible[i] = 0;
4681                                 }
4682                         }
4683                 }
4684         }
4685         else
4686         {
4687                 // no worldmodel or it can't check visibility
4688                 for (i = 0;i < r_refdef.scene.numentities;i++)
4689                 {
4690                         ent = r_refdef.scene.entities[i];
4691                         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));
4692                 }
4693         }
4694 }
4695
4696 /// only used if skyrendermasked, and normally returns false
4697 int R_DrawBrushModelsSky (void)
4698 {
4699         int i, sky;
4700         entity_render_t *ent;
4701
4702         sky = false;
4703         for (i = 0;i < r_refdef.scene.numentities;i++)
4704         {
4705                 if (!r_refdef.viewcache.entityvisible[i])
4706                         continue;
4707                 ent = r_refdef.scene.entities[i];
4708                 if (!ent->model || !ent->model->DrawSky)
4709                         continue;
4710                 ent->model->DrawSky(ent);
4711                 sky = true;
4712         }
4713         return sky;
4714 }
4715
4716 static void R_DrawNoModel(entity_render_t *ent);
4717 static void R_DrawModels(void)
4718 {
4719         int i;
4720         entity_render_t *ent;
4721
4722         for (i = 0;i < r_refdef.scene.numentities;i++)
4723         {
4724                 if (!r_refdef.viewcache.entityvisible[i])
4725                         continue;
4726                 ent = r_refdef.scene.entities[i];
4727                 r_refdef.stats.entities++;
4728                 if (ent->model && ent->model->Draw != NULL)
4729                         ent->model->Draw(ent);
4730                 else
4731                         R_DrawNoModel(ent);
4732         }
4733 }
4734
4735 static void R_DrawModelsDepth(void)
4736 {
4737         int i;
4738         entity_render_t *ent;
4739
4740         for (i = 0;i < r_refdef.scene.numentities;i++)
4741         {
4742                 if (!r_refdef.viewcache.entityvisible[i])
4743                         continue;
4744                 ent = r_refdef.scene.entities[i];
4745                 if (ent->model && ent->model->DrawDepth != NULL)
4746                         ent->model->DrawDepth(ent);
4747         }
4748 }
4749
4750 static void R_DrawModelsDebug(void)
4751 {
4752         int i;
4753         entity_render_t *ent;
4754
4755         for (i = 0;i < r_refdef.scene.numentities;i++)
4756         {
4757                 if (!r_refdef.viewcache.entityvisible[i])
4758                         continue;
4759                 ent = r_refdef.scene.entities[i];
4760                 if (ent->model && ent->model->DrawDebug != NULL)
4761                         ent->model->DrawDebug(ent);
4762         }
4763 }
4764
4765 static void R_DrawModelsAddWaterPlanes(void)
4766 {
4767         int i;
4768         entity_render_t *ent;
4769
4770         for (i = 0;i < r_refdef.scene.numentities;i++)
4771         {
4772                 if (!r_refdef.viewcache.entityvisible[i])
4773                         continue;
4774                 ent = r_refdef.scene.entities[i];
4775                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4776                         ent->model->DrawAddWaterPlanes(ent);
4777         }
4778 }
4779
4780 static void R_View_SetFrustum(void)
4781 {
4782         int i;
4783         double slopex, slopey;
4784         vec3_t forward, left, up, origin;
4785
4786         // we can't trust r_refdef.view.forward and friends in reflected scenes
4787         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4788
4789 #if 0
4790         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4791         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4792         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4793         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4794         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4795         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4796         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4797         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4798         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4799         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4800         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4801         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4802 #endif
4803
4804 #if 0
4805         zNear = r_refdef.nearclip;
4806         nudge = 1.0 - 1.0 / (1<<23);
4807         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4808         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4809         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4810         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4811         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4812         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4813         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4814         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4815 #endif
4816
4817
4818
4819 #if 0
4820         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4821         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4822         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4823         r_refdef.view.frustum[0].dist = m[15] - m[12];
4824
4825         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4826         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4827         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4828         r_refdef.view.frustum[1].dist = m[15] + m[12];
4829
4830         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4831         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4832         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4833         r_refdef.view.frustum[2].dist = m[15] - m[13];
4834
4835         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4836         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4837         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4838         r_refdef.view.frustum[3].dist = m[15] + m[13];
4839
4840         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4841         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4842         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4843         r_refdef.view.frustum[4].dist = m[15] - m[14];
4844
4845         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4846         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4847         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4848         r_refdef.view.frustum[5].dist = m[15] + m[14];
4849 #endif
4850
4851         if (r_refdef.view.useperspective)
4852         {
4853                 slopex = 1.0 / r_refdef.view.frustum_x;
4854                 slopey = 1.0 / r_refdef.view.frustum_y;
4855                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4856                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
4857                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
4858                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
4859                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4860
4861                 // Leaving those out was a mistake, those were in the old code, and they
4862                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4863                 // I couldn't reproduce it after adding those normalizations. --blub
4864                 VectorNormalize(r_refdef.view.frustum[0].normal);
4865                 VectorNormalize(r_refdef.view.frustum[1].normal);
4866                 VectorNormalize(r_refdef.view.frustum[2].normal);
4867                 VectorNormalize(r_refdef.view.frustum[3].normal);
4868
4869                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4870                 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]);
4871                 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]);
4872                 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]);
4873                 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]);
4874
4875                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4876                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4877                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4878                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4879                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4880         }
4881         else
4882         {
4883                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4884                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4885                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4886                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4887                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4888                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4889                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4890                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4891                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4892                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4893         }
4894         r_refdef.view.numfrustumplanes = 5;
4895
4896         if (r_refdef.view.useclipplane)
4897         {
4898                 r_refdef.view.numfrustumplanes = 6;
4899                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4900         }
4901
4902         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4903                 PlaneClassify(r_refdef.view.frustum + i);
4904
4905         // LordHavoc: note to all quake engine coders, Quake had a special case
4906         // for 90 degrees which assumed a square view (wrong), so I removed it,
4907         // Quake2 has it disabled as well.
4908
4909         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4910         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4911         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4912         //PlaneClassify(&frustum[0]);
4913
4914         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4915         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4916         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4917         //PlaneClassify(&frustum[1]);
4918
4919         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4920         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4921         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4922         //PlaneClassify(&frustum[2]);
4923
4924         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4925         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4926         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4927         //PlaneClassify(&frustum[3]);
4928
4929         // nearclip plane
4930         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4931         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4932         //PlaneClassify(&frustum[4]);
4933 }
4934
4935 void R_View_Update(void)
4936 {
4937         R_Main_ResizeViewCache();
4938         R_View_SetFrustum();
4939         R_View_WorldVisibility(r_refdef.view.useclipplane);
4940         R_View_UpdateEntityVisible();
4941         R_View_UpdateEntityLighting();
4942 }
4943
4944 void R_SetupView(qboolean allowwaterclippingplane)
4945 {
4946         const float *customclipplane = NULL;
4947         float plane[4];
4948         if (r_refdef.view.useclipplane && allowwaterclippingplane)
4949         {
4950                 // LordHavoc: couldn't figure out how to make this approach the
4951                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4952                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4953                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4954                         dist = r_refdef.view.clipplane.dist;
4955                 plane[0] = r_refdef.view.clipplane.normal[0];
4956                 plane[1] = r_refdef.view.clipplane.normal[1];
4957                 plane[2] = r_refdef.view.clipplane.normal[2];
4958                 plane[3] = dist;
4959                 customclipplane = plane;
4960         }
4961
4962         if (!r_refdef.view.useperspective)
4963                 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);
4964         else if (vid.stencil && r_useinfinitefarclip.integer)
4965                 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);
4966         else
4967                 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);
4968         R_SetViewport(&r_refdef.view.viewport);
4969 }
4970
4971 void R_EntityMatrix(const matrix4x4_t *matrix)
4972 {
4973         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
4974         {
4975                 gl_modelmatrixchanged = false;
4976                 gl_modelmatrix = *matrix;
4977                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
4978                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
4979                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
4980                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
4981                 CHECKGLERROR
4982                 switch(vid.renderpath)
4983                 {
4984                 case RENDERPATH_GL20:
4985                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4986                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4987                         break;
4988                 case RENDERPATH_CGGL:
4989 #ifdef SUPPORTCG
4990                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix >= 0) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4991                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4992 #endif
4993                         break;
4994                 case RENDERPATH_GL13:
4995                 case RENDERPATH_GL11:
4996                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4997                         break;
4998                 }
4999         }
5000 }
5001
5002 void R_ResetViewRendering2D(void)
5003 {
5004         r_viewport_t viewport;
5005         DrawQ_Finish();
5006
5007         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5008         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);
5009         R_SetViewport(&viewport);
5010         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5011         GL_Color(1, 1, 1, 1);
5012         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5013         GL_BlendFunc(GL_ONE, GL_ZERO);
5014         GL_AlphaTest(false);
5015         GL_ScissorTest(false);
5016         GL_DepthMask(false);
5017         GL_DepthRange(0, 1);
5018         GL_DepthTest(false);
5019         R_EntityMatrix(&identitymatrix);
5020         R_Mesh_ResetTextureState();
5021         GL_PolygonOffset(0, 0);
5022         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5023         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5024         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
5025         qglStencilMask(~0);CHECKGLERROR
5026         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
5027         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
5028         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
5029 }
5030
5031 void R_ResetViewRendering3D(void)
5032 {
5033         DrawQ_Finish();
5034
5035         R_SetupView(true);
5036         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5037         GL_Color(1, 1, 1, 1);
5038         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5039         GL_BlendFunc(GL_ONE, GL_ZERO);
5040         GL_AlphaTest(false);
5041         GL_ScissorTest(true);
5042         GL_DepthMask(true);
5043         GL_DepthRange(0, 1);
5044         GL_DepthTest(true);
5045         R_EntityMatrix(&identitymatrix);
5046         R_Mesh_ResetTextureState();
5047         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5048         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5049         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5050         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
5051         qglStencilMask(~0);CHECKGLERROR
5052         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
5053         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
5054         GL_CullFace(r_refdef.view.cullface_back);
5055 }
5056
5057 void R_RenderScene(void);
5058 void R_RenderWaterPlanes(void);
5059
5060 static void R_Water_StartFrame(void)
5061 {
5062         int i;
5063         int waterwidth, waterheight, texturewidth, textureheight;
5064         r_waterstate_waterplane_t *p;
5065
5066         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5067                 return;
5068
5069         switch(vid.renderpath)
5070         {
5071         case RENDERPATH_GL20:
5072         case RENDERPATH_CGGL:
5073                 break;
5074         case RENDERPATH_GL13:
5075         case RENDERPATH_GL11:
5076                 return;
5077         }
5078
5079         // set waterwidth and waterheight to the water resolution that will be
5080         // used (often less than the screen resolution for faster rendering)
5081         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5082         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5083
5084         // calculate desired texture sizes
5085         // can't use water if the card does not support the texture size
5086         if (!r_water.integer || r_showsurfaces.integer)
5087                 texturewidth = textureheight = waterwidth = waterheight = 0;
5088         else if (vid.support.arb_texture_non_power_of_two)
5089         {
5090                 texturewidth = waterwidth;
5091                 textureheight = waterheight;
5092         }
5093         else
5094         {
5095                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5096                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5097         }
5098
5099         // allocate textures as needed
5100         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
5101         {
5102                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5103                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5104                 {
5105                         if (p->texture_refraction)
5106                                 R_FreeTexture(p->texture_refraction);
5107                         p->texture_refraction = NULL;
5108                         if (p->texture_reflection)
5109                                 R_FreeTexture(p->texture_reflection);
5110                         p->texture_reflection = NULL;
5111                 }
5112                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5113                 r_waterstate.texturewidth = texturewidth;
5114                 r_waterstate.textureheight = textureheight;
5115         }
5116
5117         if (r_waterstate.texturewidth)
5118         {
5119                 r_waterstate.enabled = true;
5120
5121                 // when doing a reduced render (HDR) we want to use a smaller area
5122                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5123                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5124
5125                 // set up variables that will be used in shader setup
5126                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5127                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5128                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5129                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5130         }
5131
5132         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5133         r_waterstate.numwaterplanes = 0;
5134 }
5135
5136 void R_Water_AddWaterPlane(msurface_t *surface)
5137 {
5138         int triangleindex, planeindex;
5139         const int *e;
5140         vec3_t vert[3];
5141         vec3_t normal;
5142         vec3_t center;
5143         mplane_t plane;
5144         r_waterstate_waterplane_t *p;
5145         texture_t *t = R_GetCurrentTexture(surface->texture);
5146         // just use the first triangle with a valid normal for any decisions
5147         VectorClear(normal);
5148         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5149         {
5150                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5151                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5152                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5153                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5154                 if (VectorLength2(normal) >= 0.001)
5155                         break;
5156         }
5157
5158         VectorCopy(normal, plane.normal);
5159         VectorNormalize(plane.normal);
5160         plane.dist = DotProduct(vert[0], plane.normal);
5161         PlaneClassify(&plane);
5162         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5163         {
5164                 // skip backfaces (except if nocullface is set)
5165                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5166                         return;
5167                 VectorNegate(plane.normal, plane.normal);
5168                 plane.dist *= -1;
5169                 PlaneClassify(&plane);
5170         }
5171
5172
5173         // find a matching plane if there is one
5174         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5175                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5176                         break;
5177         if (planeindex >= r_waterstate.maxwaterplanes)
5178                 return; // nothing we can do, out of planes
5179
5180         // if this triangle does not fit any known plane rendered this frame, add one
5181         if (planeindex >= r_waterstate.numwaterplanes)
5182         {
5183                 // store the new plane
5184                 r_waterstate.numwaterplanes++;
5185                 p->plane = plane;
5186                 // clear materialflags and pvs
5187                 p->materialflags = 0;
5188                 p->pvsvalid = false;
5189         }
5190         // merge this surface's materialflags into the waterplane
5191         p->materialflags |= t->currentmaterialflags;
5192         // merge this surface's PVS into the waterplane
5193         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5194         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5195          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5196         {
5197                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5198                 p->pvsvalid = true;
5199         }
5200 }
5201
5202 static void R_Water_ProcessPlanes(void)
5203 {
5204         r_refdef_view_t originalview;
5205         r_refdef_view_t myview;
5206         int planeindex;
5207         r_waterstate_waterplane_t *p;
5208
5209         originalview = r_refdef.view;
5210
5211         // make sure enough textures are allocated
5212         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5213         {
5214                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5215                 {
5216                         if (!p->texture_refraction)
5217                                 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);
5218                         if (!p->texture_refraction)
5219                                 goto error;
5220                 }
5221
5222                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5223                 {
5224                         if (!p->texture_reflection)
5225                                 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);
5226                         if (!p->texture_reflection)
5227                                 goto error;
5228                 }
5229         }
5230
5231         // render views
5232         r_refdef.view = originalview;
5233         r_refdef.view.showdebug = false;
5234         r_refdef.view.width = r_waterstate.waterwidth;
5235         r_refdef.view.height = r_waterstate.waterheight;
5236         r_refdef.view.useclipplane = true;
5237         myview = r_refdef.view;
5238         r_waterstate.renderingscene = true;
5239         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5240         {
5241                 // render the normal view scene and copy into texture
5242                 // (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)
5243                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5244                 {
5245                         r_refdef.view = myview;
5246                         r_refdef.view.clipplane = p->plane;
5247                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5248                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5249                         PlaneClassify(&r_refdef.view.clipplane);
5250
5251                         R_ResetViewRendering3D();
5252                         R_ClearScreen(r_refdef.fogenabled);
5253                         R_View_Update();
5254                         R_RenderScene();
5255
5256                         R_Mesh_CopyToTexture(R_GetTexture(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);
5257                 }
5258
5259                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5260                 {
5261                         r_refdef.view = myview;
5262                         // render reflected scene and copy into texture
5263                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5264                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5265                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5266                         r_refdef.view.clipplane = p->plane;
5267                         // reverse the cullface settings for this render
5268                         r_refdef.view.cullface_front = GL_FRONT;
5269                         r_refdef.view.cullface_back = GL_BACK;
5270                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5271                         {
5272                                 r_refdef.view.usecustompvs = true;
5273                                 if (p->pvsvalid)
5274                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5275                                 else
5276                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5277                         }
5278
5279                         R_ResetViewRendering3D();
5280                         R_ClearScreen(r_refdef.fogenabled);
5281                         R_View_Update();
5282                         R_RenderScene();
5283
5284                         R_Mesh_CopyToTexture(R_GetTexture(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);
5285                 }
5286         }
5287         r_waterstate.renderingscene = false;
5288         r_refdef.view = originalview;
5289         R_ResetViewRendering3D();
5290         R_ClearScreen(r_refdef.fogenabled);
5291         R_View_Update();
5292         return;
5293 error:
5294         r_refdef.view = originalview;
5295         r_waterstate.renderingscene = false;
5296         Cvar_SetValueQuick(&r_water, 0);
5297         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5298         return;
5299 }
5300
5301 void R_Bloom_StartFrame(void)
5302 {
5303         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5304
5305         switch(vid.renderpath)
5306         {
5307         case RENDERPATH_GL20:
5308         case RENDERPATH_CGGL:
5309                 break;
5310         case RENDERPATH_GL13:
5311         case RENDERPATH_GL11:
5312                 return;
5313         }
5314
5315         // set bloomwidth and bloomheight to the bloom resolution that will be
5316         // used (often less than the screen resolution for faster rendering)
5317         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5318         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5319         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5320         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5321         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5322
5323         // calculate desired texture sizes
5324         if (vid.support.arb_texture_non_power_of_two)
5325         {
5326                 screentexturewidth = r_refdef.view.width;
5327                 screentextureheight = r_refdef.view.height;
5328                 bloomtexturewidth = r_bloomstate.bloomwidth;
5329                 bloomtextureheight = r_bloomstate.bloomheight;
5330         }
5331         else
5332         {
5333                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5334                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5335                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5336                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5337         }
5338
5339         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))
5340         {
5341                 Cvar_SetValueQuick(&r_hdr, 0);
5342                 Cvar_SetValueQuick(&r_bloom, 0);
5343                 Cvar_SetValueQuick(&r_motionblur, 0);
5344                 Cvar_SetValueQuick(&r_damageblur, 0);
5345         }
5346
5347         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)))
5348                 screentexturewidth = screentextureheight = 0;
5349         if (!r_hdr.integer && !r_bloom.integer)
5350                 bloomtexturewidth = bloomtextureheight = 0;
5351
5352         // allocate textures as needed
5353         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5354         {
5355                 if (r_bloomstate.texture_screen)
5356                         R_FreeTexture(r_bloomstate.texture_screen);
5357                 r_bloomstate.texture_screen = NULL;
5358                 r_bloomstate.screentexturewidth = screentexturewidth;
5359                 r_bloomstate.screentextureheight = screentextureheight;
5360                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5361                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
5362         }
5363         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5364         {
5365                 if (r_bloomstate.texture_bloom)
5366                         R_FreeTexture(r_bloomstate.texture_bloom);
5367                 r_bloomstate.texture_bloom = NULL;
5368                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5369                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5370                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5371                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
5372         }
5373
5374         // when doing a reduced render (HDR) we want to use a smaller area
5375         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5376         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5377         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5378         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5379         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5380
5381         // set up a texcoord array for the full resolution screen image
5382         // (we have to keep this around to copy back during final render)
5383         r_bloomstate.screentexcoord2f[0] = 0;
5384         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5385         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5386         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5387         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5388         r_bloomstate.screentexcoord2f[5] = 0;
5389         r_bloomstate.screentexcoord2f[6] = 0;
5390         r_bloomstate.screentexcoord2f[7] = 0;
5391
5392         // set up a texcoord array for the reduced resolution bloom image
5393         // (which will be additive blended over the screen image)
5394         r_bloomstate.bloomtexcoord2f[0] = 0;
5395         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5396         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5397         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5398         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5399         r_bloomstate.bloomtexcoord2f[5] = 0;
5400         r_bloomstate.bloomtexcoord2f[6] = 0;
5401         r_bloomstate.bloomtexcoord2f[7] = 0;
5402
5403         if (r_hdr.integer || r_bloom.integer)
5404         {
5405                 r_bloomstate.enabled = true;
5406                 r_bloomstate.hdr = r_hdr.integer != 0;
5407         }
5408
5409         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);
5410 }
5411
5412 void R_Bloom_CopyBloomTexture(float colorscale)
5413 {
5414         r_refdef.stats.bloom++;
5415
5416         // scale down screen texture to the bloom texture size
5417         CHECKGLERROR
5418         R_SetViewport(&r_bloomstate.viewport);
5419         GL_BlendFunc(GL_ONE, GL_ZERO);
5420         GL_Color(colorscale, colorscale, colorscale, 1);
5421         // TODO: optimize with multitexture or GLSL
5422         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5423         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5424         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5425         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5426
5427         // we now have a bloom image in the framebuffer
5428         // copy it into the bloom image texture for later processing
5429         R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5430         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5431 }
5432
5433 void R_Bloom_CopyHDRTexture(void)
5434 {
5435         R_Mesh_CopyToTexture(R_GetTexture(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);
5436         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5437 }
5438
5439 void R_Bloom_MakeTexture(void)
5440 {
5441         int x, range, dir;
5442         float xoffset, yoffset, r, brighten;
5443
5444         r_refdef.stats.bloom++;
5445
5446         R_ResetViewRendering2D();
5447         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5448         R_Mesh_ColorPointer(NULL, 0, 0);
5449
5450         // we have a bloom image in the framebuffer
5451         CHECKGLERROR
5452         R_SetViewport(&r_bloomstate.viewport);
5453
5454         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5455         {
5456                 x *= 2;
5457                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5458                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5459                 GL_Color(r, r, r, 1);
5460                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5461                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5462                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5463                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5464
5465                 // copy the vertically blurred bloom view to a texture
5466                 GL_ActiveTexture(0);
5467                 CHECKGLERROR
5468                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
5469                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5470         }
5471
5472         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5473         brighten = r_bloom_brighten.value;
5474         if (r_hdr.integer)
5475                 brighten *= r_hdr_range.value;
5476         brighten = sqrt(brighten);
5477         if(range >= 1)
5478                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5479         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5480         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
5481
5482         for (dir = 0;dir < 2;dir++)
5483         {
5484                 // blend on at multiple vertical offsets to achieve a vertical blur
5485                 // TODO: do offset blends using GLSL
5486                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5487                 GL_BlendFunc(GL_ONE, GL_ZERO);
5488                 for (x = -range;x <= range;x++)
5489                 {
5490                         if (!dir){xoffset = 0;yoffset = x;}
5491                         else {xoffset = x;yoffset = 0;}
5492                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5493                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5494                         // compute a texcoord array with the specified x and y offset
5495                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5496                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5497                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5498                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5499                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5500                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5501                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5502                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5503                         // this r value looks like a 'dot' particle, fading sharply to
5504                         // black at the edges
5505                         // (probably not realistic but looks good enough)
5506                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5507                         //r = brighten/(range*2+1);
5508                         r = brighten / (range * 2 + 1);
5509                         if(range >= 1)
5510                                 r *= (1 - x*x/(float)(range*range));
5511                         GL_Color(r, r, r, 1);
5512                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5513                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5514                         GL_BlendFunc(GL_ONE, GL_ONE);
5515                 }
5516
5517                 // copy the vertically blurred bloom view to a texture
5518                 GL_ActiveTexture(0);
5519                 CHECKGLERROR
5520                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
5521                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5522         }
5523
5524         // apply subtract last
5525         // (just like it would be in a GLSL shader)
5526         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
5527         {
5528                 GL_BlendFunc(GL_ONE, GL_ZERO);
5529                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5530                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5531                 GL_Color(1, 1, 1, 1);
5532                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5533                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5534
5535                 GL_BlendFunc(GL_ONE, GL_ONE);
5536                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
5537                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5538                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5539                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
5540                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5541                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5542                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
5543
5544                 // copy the darkened bloom view to a texture
5545                 R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5546                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5547         }
5548 }
5549
5550 void R_HDR_RenderBloomTexture(void)
5551 {
5552         int oldwidth, oldheight;
5553         float oldcolorscale;
5554
5555         oldcolorscale = r_refdef.view.colorscale;
5556         oldwidth = r_refdef.view.width;
5557         oldheight = r_refdef.view.height;
5558         r_refdef.view.width = r_bloomstate.bloomwidth;
5559         r_refdef.view.height = r_bloomstate.bloomheight;
5560
5561         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5562         // TODO: add exposure compensation features
5563         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5564
5565         r_refdef.view.showdebug = false;
5566         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5567
5568         R_ResetViewRendering3D();
5569
5570         R_ClearScreen(r_refdef.fogenabled);
5571         if (r_timereport_active)
5572                 R_TimeReport("HDRclear");
5573
5574         R_View_Update();
5575         if (r_timereport_active)
5576                 R_TimeReport("visibility");
5577
5578         // only do secondary renders with HDR if r_hdr is 2 or higher
5579         r_waterstate.numwaterplanes = 0;
5580         if (r_waterstate.enabled && r_hdr.integer >= 2)
5581                 R_RenderWaterPlanes();
5582
5583         r_refdef.view.showdebug = true;
5584         R_RenderScene();
5585         r_waterstate.numwaterplanes = 0;
5586
5587         R_ResetViewRendering2D();
5588
5589         R_Bloom_CopyHDRTexture();
5590         R_Bloom_MakeTexture();
5591
5592         // restore the view settings
5593         r_refdef.view.width = oldwidth;
5594         r_refdef.view.height = oldheight;
5595         r_refdef.view.colorscale = oldcolorscale;
5596         r_frame++; // used only by R_GetCurrentTexture
5597
5598         R_ResetViewRendering3D();
5599
5600         R_ClearScreen(r_refdef.fogenabled);
5601         if (r_timereport_active)
5602                 R_TimeReport("viewclear");
5603 }
5604
5605 static void R_BlendView(void)
5606 {
5607         unsigned int permutation;
5608         float uservecs[4][4];
5609
5610         switch (vid.renderpath)
5611         {
5612         case RENDERPATH_GL20:
5613         case RENDERPATH_CGGL:
5614                 permutation =
5615                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5616                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5617                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5618                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5619                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5620
5621                 if (r_bloomstate.texture_screen)
5622                 {
5623                         // make sure the buffer is available
5624                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5625
5626                         R_ResetViewRendering2D();
5627                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5628                         R_Mesh_ColorPointer(NULL, 0, 0);
5629
5630                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5631                         {
5632                                 // declare variables
5633                                 float speed;
5634                                 static float avgspeed;
5635
5636                                 speed = VectorLength(cl.movement_velocity);
5637
5638                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5639                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5640
5641                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5642                                 speed = bound(0, speed, 1);
5643                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5644
5645                                 // calculate values into a standard alpha
5646                                 cl.motionbluralpha = 1 - exp(-
5647                                                 (
5648                                                  (r_motionblur.value * speed / 80)
5649                                                  +
5650                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5651                                                 )
5652                                                 /
5653                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5654                                            );
5655
5656                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5657                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5658                                 // apply the blur
5659                                 if (cl.motionbluralpha > 0)
5660                                 {
5661                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5662                                         GL_Color(1, 1, 1, cl.motionbluralpha);
5663                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5664                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5665                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5666                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5667                                 }
5668                         }
5669
5670                         // copy view into the screen texture
5671                         R_Mesh_CopyToTexture(R_GetTexture(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);
5672                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5673                 }
5674                 else if (!r_bloomstate.texture_bloom)
5675                 {
5676                         // we may still have to do view tint...
5677                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
5678                         {
5679                                 // apply a color tint to the whole view
5680                                 R_ResetViewRendering2D();
5681                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5682                                 R_Mesh_ColorPointer(NULL, 0, 0);
5683                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5684                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5685                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5686                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5687                         }
5688                         break; // no screen processing, no bloom, skip it
5689                 }
5690
5691                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
5692                 {
5693                         // render simple bloom effect
5694                         // copy the screen and shrink it and darken it for the bloom process
5695                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
5696                         // make the bloom texture
5697                         R_Bloom_MakeTexture();
5698                 }
5699
5700 #if _MSC_VER >= 1400
5701 #define sscanf sscanf_s
5702 #endif
5703                 memset(uservecs, 0, sizeof(uservecs));
5704                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
5705                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
5706                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
5707                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
5708
5709                 R_ResetViewRendering2D();
5710                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5711                 R_Mesh_ColorPointer(NULL, 0, 0);
5712                 GL_Color(1, 1, 1, 1);
5713                 GL_BlendFunc(GL_ONE, GL_ZERO);
5714                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5715                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5716
5717                 switch(vid.renderpath)
5718                 {
5719                 case RENDERPATH_GL20:
5720                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
5721                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , R_GetTexture(r_bloomstate.texture_screen));
5722                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , R_GetTexture(r_bloomstate.texture_bloom ));
5723                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps       ));
5724                         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]);
5725                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
5726                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
5727                         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]);
5728                         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]);
5729                         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]);
5730                         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]);
5731                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
5732                         break;
5733                 case RENDERPATH_CGGL:
5734 #ifdef SUPPORTCG
5735                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
5736                         if (r_cg_permutation->fp_Texture_First     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First     , R_GetTexture(r_bloomstate.texture_screen));
5737                         if (r_cg_permutation->fp_Texture_Second    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second    , R_GetTexture(r_bloomstate.texture_bloom ));
5738                         if (r_cg_permutation->fp_Texture_GammaRamps) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_GammaRamps, R_GetTexture(r_texture_gammaramps       ));
5739                         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]);
5740                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);
5741                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
5742                         if (r_cg_permutation->fp_UserVec1          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
5743                         if (r_cg_permutation->fp_UserVec2          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
5744                         if (r_cg_permutation->fp_UserVec3          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
5745                         if (r_cg_permutation->fp_UserVec4          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
5746                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);
5747 #endif
5748                         break;
5749                 default:
5750                         break;
5751                 }
5752                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5753                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5754                 break;
5755         case RENDERPATH_GL13:
5756         case RENDERPATH_GL11:
5757                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
5758                 {
5759                         // apply a color tint to the whole view
5760                         R_ResetViewRendering2D();
5761                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5762                         R_Mesh_ColorPointer(NULL, 0, 0);
5763                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5764                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5765                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5766                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5767                 }
5768                 break;
5769         }
5770 }
5771
5772 matrix4x4_t r_waterscrollmatrix;
5773
5774 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
5775 {
5776         if (r_refdef.fog_density)
5777         {
5778                 r_refdef.fogcolor[0] = r_refdef.fog_red;
5779                 r_refdef.fogcolor[1] = r_refdef.fog_green;
5780                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5781
5782                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5783                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5784                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5785                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5786
5787                 {
5788                         vec3_t fogvec;
5789                         VectorCopy(r_refdef.fogcolor, fogvec);
5790                         //   color.rgb *= ContrastBoost * SceneBrightness;
5791                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5792                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5793                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5794                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5795                 }
5796         }
5797 }
5798
5799 void R_UpdateVariables(void)
5800 {
5801         R_Textures_Frame();
5802
5803         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
5804
5805         r_refdef.farclip = r_farclip_base.value;
5806         if (r_refdef.scene.worldmodel)
5807                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5808         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5809
5810         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5811                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5812         r_refdef.polygonfactor = 0;
5813         r_refdef.polygonoffset = 0;
5814         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5815         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5816
5817         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5818         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5819         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5820         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5821         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5822         if (r_showsurfaces.integer)
5823         {
5824                 r_refdef.scene.rtworld = false;
5825                 r_refdef.scene.rtworldshadows = false;
5826                 r_refdef.scene.rtdlight = false;
5827                 r_refdef.scene.rtdlightshadows = false;
5828                 r_refdef.lightmapintensity = 0;
5829         }
5830
5831         if (gamemode == GAME_NEHAHRA)
5832         {
5833                 if (gl_fogenable.integer)
5834                 {
5835                         r_refdef.oldgl_fogenable = true;
5836                         r_refdef.fog_density = gl_fogdensity.value;
5837                         r_refdef.fog_red = gl_fogred.value;
5838                         r_refdef.fog_green = gl_foggreen.value;
5839                         r_refdef.fog_blue = gl_fogblue.value;
5840                         r_refdef.fog_alpha = 1;
5841                         r_refdef.fog_start = 0;
5842                         r_refdef.fog_end = gl_skyclip.value;
5843                         r_refdef.fog_height = 1<<30;
5844                         r_refdef.fog_fadedepth = 128;
5845                 }
5846                 else if (r_refdef.oldgl_fogenable)
5847                 {
5848                         r_refdef.oldgl_fogenable = false;
5849                         r_refdef.fog_density = 0;
5850                         r_refdef.fog_red = 0;
5851                         r_refdef.fog_green = 0;
5852                         r_refdef.fog_blue = 0;
5853                         r_refdef.fog_alpha = 0;
5854                         r_refdef.fog_start = 0;
5855                         r_refdef.fog_end = 0;
5856                         r_refdef.fog_height = 1<<30;
5857                         r_refdef.fog_fadedepth = 128;
5858                 }
5859         }
5860
5861         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5862         r_refdef.fog_start = max(0, r_refdef.fog_start);
5863         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5864
5865         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5866
5867         if (r_refdef.fog_density && r_drawfog.integer)
5868         {
5869                 r_refdef.fogenabled = true;
5870                 // this is the point where the fog reaches 0.9986 alpha, which we
5871                 // consider a good enough cutoff point for the texture
5872                 // (0.9986 * 256 == 255.6)
5873                 if (r_fog_exp2.integer)
5874                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5875                 else
5876                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5877                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5878                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5879                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5880                 // fog color was already set
5881                 // update the fog texture
5882                 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)
5883                         R_BuildFogTexture();
5884         }
5885         else
5886                 r_refdef.fogenabled = false;
5887
5888         switch(vid.renderpath)
5889         {
5890         case RENDERPATH_GL20:
5891         case RENDERPATH_CGGL:
5892                 if(v_glslgamma.integer && !vid_gammatables_trivial)
5893                 {
5894                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5895                         {
5896                                 // build GLSL gamma texture
5897 #define RAMPWIDTH 256
5898                                 unsigned short ramp[RAMPWIDTH * 3];
5899                                 unsigned char rampbgr[RAMPWIDTH][4];
5900                                 int i;
5901
5902                                 r_texture_gammaramps_serial = vid_gammatables_serial;
5903
5904                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5905                                 for(i = 0; i < RAMPWIDTH; ++i)
5906                                 {
5907                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5908                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5909                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5910                                         rampbgr[i][3] = 0;
5911                                 }
5912                                 if (r_texture_gammaramps)
5913                                 {
5914                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5915                                 }
5916                                 else
5917                                 {
5918                                         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);
5919                                 }
5920                         }
5921                 }
5922                 else
5923                 {
5924                         // remove GLSL gamma texture
5925                 }
5926                 break;
5927         case RENDERPATH_GL13:
5928         case RENDERPATH_GL11:
5929                 break;
5930         }
5931 }
5932
5933 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5934 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5935 /*
5936 ================
5937 R_SelectScene
5938 ================
5939 */
5940 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5941         if( scenetype != r_currentscenetype ) {
5942                 // store the old scenetype
5943                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5944                 r_currentscenetype = scenetype;
5945                 // move in the new scene
5946                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5947         }
5948 }
5949
5950 /*
5951 ================
5952 R_GetScenePointer
5953 ================
5954 */
5955 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5956 {
5957         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5958         if( scenetype == r_currentscenetype ) {
5959                 return &r_refdef.scene;
5960         } else {
5961                 return &r_scenes_store[ scenetype ];
5962         }
5963 }
5964
5965 /*
5966 ================
5967 R_RenderView
5968 ================
5969 */
5970 void R_RenderView(void)
5971 {
5972         if (r_timereport_active)
5973                 R_TimeReport("start");
5974         r_frame++; // used only by R_GetCurrentTexture
5975         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5976
5977         if (!r_drawentities.integer)
5978                 r_refdef.scene.numentities = 0;
5979
5980         R_AnimCache_ClearCache();
5981         R_FrameData_NewFrame();
5982
5983         if (r_refdef.view.isoverlay)
5984         {
5985                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5986                 GL_Clear( GL_DEPTH_BUFFER_BIT );
5987                 R_TimeReport("depthclear");
5988
5989                 r_refdef.view.showdebug = false;
5990
5991                 r_waterstate.enabled = false;
5992                 r_waterstate.numwaterplanes = 0;
5993
5994                 R_RenderScene();
5995
5996                 CHECKGLERROR
5997                 return;
5998         }
5999
6000         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
6001                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6002
6003         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
6004
6005         // break apart the view matrix into vectors for various purposes
6006         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
6007         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
6008         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
6009         VectorNegate(r_refdef.view.left, r_refdef.view.right);
6010         // make an inverted copy of the view matrix for tracking sprites
6011         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
6012
6013         R_Shadow_UpdateWorldLightSelection();
6014
6015         R_Bloom_StartFrame();
6016         R_Water_StartFrame();
6017
6018         CHECKGLERROR
6019         if (r_timereport_active)
6020                 R_TimeReport("viewsetup");
6021
6022         R_ResetViewRendering3D();
6023
6024         if (r_refdef.view.clear || r_refdef.fogenabled)
6025         {
6026                 R_ClearScreen(r_refdef.fogenabled);
6027                 if (r_timereport_active)
6028                         R_TimeReport("viewclear");
6029         }
6030         r_refdef.view.clear = true;
6031
6032         // this produces a bloom texture to be used in R_BlendView() later
6033         if (r_hdr.integer && r_bloomstate.bloomwidth)
6034                 R_HDR_RenderBloomTexture();
6035
6036         r_refdef.view.showdebug = true;
6037
6038         R_View_Update();
6039         if (r_timereport_active)
6040                 R_TimeReport("visibility");
6041
6042         r_waterstate.numwaterplanes = 0;
6043         if (r_waterstate.enabled)
6044                 R_RenderWaterPlanes();
6045
6046         R_RenderScene();
6047         r_waterstate.numwaterplanes = 0;
6048
6049         R_BlendView();
6050         if (r_timereport_active)
6051                 R_TimeReport("blendview");
6052
6053         GL_Scissor(0, 0, vid.width, vid.height);
6054         GL_ScissorTest(false);
6055         CHECKGLERROR
6056 }
6057
6058 void R_RenderWaterPlanes(void)
6059 {
6060         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6061         {
6062                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6063                 if (r_timereport_active)
6064                         R_TimeReport("waterworld");
6065         }
6066
6067         // don't let sound skip if going slow
6068         if (r_refdef.scene.extraupdate)
6069                 S_ExtraUpdate ();
6070
6071         R_DrawModelsAddWaterPlanes();
6072         if (r_timereport_active)
6073                 R_TimeReport("watermodels");
6074
6075         if (r_waterstate.numwaterplanes)
6076         {
6077                 R_Water_ProcessPlanes();
6078                 if (r_timereport_active)
6079                         R_TimeReport("waterscenes");
6080         }
6081 }
6082
6083 extern void R_DrawLightningBeams (void);
6084 extern void VM_CL_AddPolygonsToMeshQueue (void);
6085 extern void R_DrawPortals (void);
6086 extern cvar_t cl_locs_show;
6087 static void R_DrawLocs(void);
6088 static void R_DrawEntityBBoxes(void);
6089 static void R_DrawModelDecals(void);
6090 extern cvar_t cl_decals_newsystem;
6091 extern qboolean r_shadow_usingdeferredprepass;
6092 void R_RenderScene(void)
6093 {
6094         r_refdef.stats.renders++;
6095
6096         R_UpdateFogColor();
6097
6098         // don't let sound skip if going slow
6099         if (r_refdef.scene.extraupdate)
6100                 S_ExtraUpdate ();
6101
6102         R_MeshQueue_BeginScene();
6103
6104         R_SkyStartFrame();
6105
6106         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);
6107
6108         if (cl.csqc_vidvars.drawworld)
6109         {
6110                 // don't let sound skip if going slow
6111                 if (r_refdef.scene.extraupdate)
6112                         S_ExtraUpdate ();
6113
6114                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6115                 {
6116                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6117                         if (r_timereport_active)
6118                                 R_TimeReport("worldsky");
6119                 }
6120
6121                 if (R_DrawBrushModelsSky() && r_timereport_active)
6122                         R_TimeReport("bmodelsky");
6123
6124                 if (skyrendermasked && skyrenderlater)
6125                 {
6126                         // we have to force off the water clipping plane while rendering sky
6127                         R_SetupView(false);
6128                         R_Sky();
6129                         R_SetupView(true);
6130                         if (r_timereport_active)
6131                                 R_TimeReport("sky");
6132                 }
6133         }
6134
6135         R_AnimCache_CacheVisibleEntities();
6136         if (r_timereport_active)
6137                 R_TimeReport("animation");
6138
6139         R_Shadow_PrepareLights();
6140         if (r_timereport_active)
6141                 R_TimeReport("preparelights");
6142
6143         if (r_shadow_usingdeferredprepass)
6144                 R_Shadow_DrawPrepass();
6145
6146         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6147         {
6148                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6149                 if (r_timereport_active)
6150                         R_TimeReport("worlddepth");
6151         }
6152         if (r_depthfirst.integer >= 2)
6153         {
6154                 R_DrawModelsDepth();
6155                 if (r_timereport_active)
6156                         R_TimeReport("modeldepth");
6157         }
6158
6159         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6160         {
6161                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6162                 if (r_timereport_active)
6163                         R_TimeReport("world");
6164         }
6165
6166         // don't let sound skip if going slow
6167         if (r_refdef.scene.extraupdate)
6168                 S_ExtraUpdate ();
6169
6170         R_DrawModels();
6171         if (r_timereport_active)
6172                 R_TimeReport("models");
6173
6174         // don't let sound skip if going slow
6175         if (r_refdef.scene.extraupdate)
6176                 S_ExtraUpdate ();
6177
6178         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6179         {
6180                 R_DrawModelShadows();
6181                 R_ResetViewRendering3D();
6182                 // don't let sound skip if going slow
6183                 if (r_refdef.scene.extraupdate)
6184                         S_ExtraUpdate ();
6185         }
6186
6187         if (!r_shadow_usingdeferredprepass)
6188         {
6189                 R_Shadow_DrawLights();
6190                 if (r_timereport_active)
6191                         R_TimeReport("rtlights");
6192         }
6193
6194         // don't let sound skip if going slow
6195         if (r_refdef.scene.extraupdate)
6196                 S_ExtraUpdate ();
6197
6198         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6199         {
6200                 R_DrawModelShadows();
6201                 R_ResetViewRendering3D();
6202                 // don't let sound skip if going slow
6203                 if (r_refdef.scene.extraupdate)
6204                         S_ExtraUpdate ();
6205         }
6206
6207         if (cl.csqc_vidvars.drawworld)
6208         {
6209                 if (cl_decals_newsystem.integer)
6210                 {
6211                         R_DrawModelDecals();
6212                         if (r_timereport_active)
6213                                 R_TimeReport("modeldecals");
6214                 }
6215                 else
6216                 {
6217                         R_DrawDecals();
6218                         if (r_timereport_active)
6219                                 R_TimeReport("decals");
6220                 }
6221
6222                 R_DrawParticles();
6223                 if (r_timereport_active)
6224                         R_TimeReport("particles");
6225
6226                 R_DrawExplosions();
6227                 if (r_timereport_active)
6228                         R_TimeReport("explosions");
6229
6230                 R_DrawLightningBeams();
6231                 if (r_timereport_active)
6232                         R_TimeReport("lightning");
6233         }
6234
6235         VM_CL_AddPolygonsToMeshQueue();
6236
6237         if (r_refdef.view.showdebug)
6238         {
6239                 if (cl_locs_show.integer)
6240                 {
6241                         R_DrawLocs();
6242                         if (r_timereport_active)
6243                                 R_TimeReport("showlocs");
6244                 }
6245
6246                 if (r_drawportals.integer)
6247                 {
6248                         R_DrawPortals();
6249                         if (r_timereport_active)
6250                                 R_TimeReport("portals");
6251                 }
6252
6253                 if (r_showbboxes.value > 0)
6254                 {
6255                         R_DrawEntityBBoxes();
6256                         if (r_timereport_active)
6257                                 R_TimeReport("bboxes");
6258                 }
6259         }
6260
6261         R_MeshQueue_RenderTransparent();
6262         if (r_timereport_active)
6263                 R_TimeReport("drawtrans");
6264
6265         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))
6266         {
6267                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6268                 if (r_timereport_active)
6269                         R_TimeReport("worlddebug");
6270                 R_DrawModelsDebug();
6271                 if (r_timereport_active)
6272                         R_TimeReport("modeldebug");
6273         }
6274
6275         if (cl.csqc_vidvars.drawworld)
6276         {
6277                 R_Shadow_DrawCoronas();
6278                 if (r_timereport_active)
6279                         R_TimeReport("coronas");
6280         }
6281
6282         // don't let sound skip if going slow
6283         if (r_refdef.scene.extraupdate)
6284                 S_ExtraUpdate ();
6285
6286         R_ResetViewRendering2D();
6287 }
6288
6289 static const unsigned short bboxelements[36] =
6290 {
6291         5, 1, 3, 5, 3, 7,
6292         6, 2, 0, 6, 0, 4,
6293         7, 3, 2, 7, 2, 6,
6294         4, 0, 1, 4, 1, 5,
6295         4, 5, 7, 4, 7, 6,
6296         1, 0, 2, 1, 2, 3,
6297 };
6298
6299 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6300 {
6301         int i;
6302         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6303
6304         RSurf_ActiveWorldEntity();
6305
6306         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6307         GL_DepthMask(false);
6308         GL_DepthRange(0, 1);
6309         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6310         R_Mesh_ResetTextureState();
6311
6312         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6313         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6314         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6315         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6316         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6317         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6318         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6319         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6320         R_FillColors(color4f, 8, cr, cg, cb, ca);
6321         if (r_refdef.fogenabled)
6322         {
6323                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6324                 {
6325                         f1 = RSurf_FogVertex(v);
6326                         f2 = 1 - f1;
6327                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6328                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6329                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6330                 }
6331         }
6332         R_Mesh_VertexPointer(vertex3f, 0, 0);
6333         R_Mesh_ColorPointer(color4f, 0, 0);
6334         R_Mesh_ResetTextureState();
6335         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6336         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
6337 }
6338
6339 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6340 {
6341         int i;
6342         float color[4];
6343         prvm_edict_t *edict;
6344         prvm_prog_t *prog_save = prog;
6345
6346         // this function draws bounding boxes of server entities
6347         if (!sv.active)
6348                 return;
6349
6350         GL_CullFace(GL_NONE);
6351         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6352
6353         prog = 0;
6354         SV_VM_Begin();
6355         for (i = 0;i < numsurfaces;i++)
6356         {
6357                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6358                 switch ((int)edict->fields.server->solid)
6359                 {
6360                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6361                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6362                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6363                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6364                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6365                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6366                 }
6367                 color[3] *= r_showbboxes.value;
6368                 color[3] = bound(0, color[3], 1);
6369                 GL_DepthTest(!r_showdisabledepthtest.integer);
6370                 GL_CullFace(r_refdef.view.cullface_front);
6371                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6372         }
6373         SV_VM_End();
6374         prog = prog_save;
6375 }
6376
6377 static void R_DrawEntityBBoxes(void)
6378 {
6379         int i;
6380         prvm_edict_t *edict;
6381         vec3_t center;
6382         prvm_prog_t *prog_save = prog;
6383
6384         // this function draws bounding boxes of server entities
6385         if (!sv.active)
6386                 return;
6387
6388         prog = 0;
6389         SV_VM_Begin();
6390         for (i = 0;i < prog->num_edicts;i++)
6391         {
6392                 edict = PRVM_EDICT_NUM(i);
6393                 if (edict->priv.server->free)
6394                         continue;
6395                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6396                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6397                         continue;
6398                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6399                         continue;
6400                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6401                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6402         }
6403         SV_VM_End();
6404         prog = prog_save;
6405 }
6406
6407 static const int nomodelelement3i[24] =
6408 {
6409         5, 2, 0,
6410         5, 1, 2,
6411         5, 0, 3,
6412         5, 3, 1,
6413         0, 2, 4,
6414         2, 1, 4,
6415         3, 0, 4,
6416         1, 3, 4
6417 };
6418
6419 static const unsigned short nomodelelement3s[24] =
6420 {
6421         5, 2, 0,
6422         5, 1, 2,
6423         5, 0, 3,
6424         5, 3, 1,
6425         0, 2, 4,
6426         2, 1, 4,
6427         3, 0, 4,
6428         1, 3, 4
6429 };
6430
6431 static const float nomodelvertex3f[6*3] =
6432 {
6433         -16,   0,   0,
6434          16,   0,   0,
6435           0, -16,   0,
6436           0,  16,   0,
6437           0,   0, -16,
6438           0,   0,  16
6439 };
6440
6441 static const float nomodelcolor4f[6*4] =
6442 {
6443         0.0f, 0.0f, 0.5f, 1.0f,
6444         0.0f, 0.0f, 0.5f, 1.0f,
6445         0.0f, 0.5f, 0.0f, 1.0f,
6446         0.0f, 0.5f, 0.0f, 1.0f,
6447         0.5f, 0.0f, 0.0f, 1.0f,
6448         0.5f, 0.0f, 0.0f, 1.0f
6449 };
6450
6451 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6452 {
6453         int i;
6454         float f1, f2, *c;
6455         float color4f[6*4];
6456
6457         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);
6458
6459         // this is only called once per entity so numsurfaces is always 1, and
6460         // surfacelist is always {0}, so this code does not handle batches
6461
6462         if (rsurface.ent_flags & RENDER_ADDITIVE)
6463         {
6464                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6465                 GL_DepthMask(false);
6466         }
6467         else if (rsurface.colormod[3] < 1)
6468         {
6469                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6470                 GL_DepthMask(false);
6471         }
6472         else
6473         {
6474                 GL_BlendFunc(GL_ONE, GL_ZERO);
6475                 GL_DepthMask(true);
6476         }
6477         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6478         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6479         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6480         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6481         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6482         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6483         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6484         R_Mesh_ColorPointer(color4f, 0, 0);
6485         for (i = 0, c = color4f;i < 6;i++, c += 4)
6486         {
6487                 c[0] *= rsurface.colormod[0];
6488                 c[1] *= rsurface.colormod[1];
6489                 c[2] *= rsurface.colormod[2];
6490                 c[3] *= rsurface.colormod[3];
6491         }
6492         if (r_refdef.fogenabled)
6493         {
6494                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6495                 {
6496                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
6497                         f2 = 1 - f1;
6498                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6499                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6500                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6501                 }
6502         }
6503         R_Mesh_ResetTextureState();
6504         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
6505 }
6506
6507 void R_DrawNoModel(entity_render_t *ent)
6508 {
6509         vec3_t org;
6510         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6511         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6512                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6513         else
6514                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6515 }
6516
6517 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6518 {
6519         vec3_t right1, right2, diff, normal;
6520
6521         VectorSubtract (org2, org1, normal);
6522
6523         // calculate 'right' vector for start
6524         VectorSubtract (r_refdef.view.origin, org1, diff);
6525         CrossProduct (normal, diff, right1);
6526         VectorNormalize (right1);
6527
6528         // calculate 'right' vector for end
6529         VectorSubtract (r_refdef.view.origin, org2, diff);
6530         CrossProduct (normal, diff, right2);
6531         VectorNormalize (right2);
6532
6533         vert[ 0] = org1[0] + width * right1[0];
6534         vert[ 1] = org1[1] + width * right1[1];
6535         vert[ 2] = org1[2] + width * right1[2];
6536         vert[ 3] = org1[0] - width * right1[0];
6537         vert[ 4] = org1[1] - width * right1[1];
6538         vert[ 5] = org1[2] - width * right1[2];
6539         vert[ 6] = org2[0] - width * right2[0];
6540         vert[ 7] = org2[1] - width * right2[1];
6541         vert[ 8] = org2[2] - width * right2[2];
6542         vert[ 9] = org2[0] + width * right2[0];
6543         vert[10] = org2[1] + width * right2[1];
6544         vert[11] = org2[2] + width * right2[2];
6545 }
6546
6547 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)
6548 {
6549         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6550         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6551         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6552         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6553         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6554         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6555         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6556         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6557         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6558         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6559         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6560         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
6561 }
6562
6563 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
6564 {
6565         int i;
6566         float *vertex3f;
6567         float v[3];
6568         VectorSet(v, x, y, z);
6569         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
6570                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
6571                         break;
6572         if (i == mesh->numvertices)
6573         {
6574                 if (mesh->numvertices < mesh->maxvertices)
6575                 {
6576                         VectorCopy(v, vertex3f);
6577                         mesh->numvertices++;
6578                 }
6579                 return mesh->numvertices;
6580         }
6581         else
6582                 return i;
6583 }
6584
6585 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
6586 {
6587         int i;
6588         int *e, element[3];
6589         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6590         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6591         e = mesh->element3i + mesh->numtriangles * 3;
6592         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
6593         {
6594                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
6595                 if (mesh->numtriangles < mesh->maxtriangles)
6596                 {
6597                         *e++ = element[0];
6598                         *e++ = element[1];
6599                         *e++ = element[2];
6600                         mesh->numtriangles++;
6601                 }
6602                 element[1] = element[2];
6603         }
6604 }
6605
6606 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
6607 {
6608         int i;
6609         int *e, element[3];
6610         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6611         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6612         e = mesh->element3i + mesh->numtriangles * 3;
6613         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
6614         {
6615                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
6616                 if (mesh->numtriangles < mesh->maxtriangles)
6617                 {
6618                         *e++ = element[0];
6619                         *e++ = element[1];
6620                         *e++ = element[2];
6621                         mesh->numtriangles++;
6622                 }
6623                 element[1] = element[2];
6624         }
6625 }
6626
6627 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
6628 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
6629 {
6630         int planenum, planenum2;
6631         int w;
6632         int tempnumpoints;
6633         mplane_t *plane, *plane2;
6634         double maxdist;
6635         double temppoints[2][256*3];
6636         // figure out how large a bounding box we need to properly compute this brush
6637         maxdist = 0;
6638         for (w = 0;w < numplanes;w++)
6639                 maxdist = max(maxdist, fabs(planes[w].dist));
6640         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
6641         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
6642         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
6643         {
6644                 w = 0;
6645                 tempnumpoints = 4;
6646                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
6647                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
6648                 {
6649                         if (planenum2 == planenum)
6650                                 continue;
6651                         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);
6652                         w = !w;
6653                 }
6654                 if (tempnumpoints < 3)
6655                         continue;
6656                 // generate elements forming a triangle fan for this polygon
6657                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
6658         }
6659 }
6660
6661 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)
6662 {
6663         texturelayer_t *layer;
6664         layer = t->currentlayers + t->currentnumlayers++;
6665         layer->type = type;
6666         layer->depthmask = depthmask;
6667         layer->blendfunc1 = blendfunc1;
6668         layer->blendfunc2 = blendfunc2;
6669         layer->texture = texture;
6670         layer->texmatrix = *matrix;
6671         layer->color[0] = r;
6672         layer->color[1] = g;
6673         layer->color[2] = b;
6674         layer->color[3] = a;
6675 }
6676
6677 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
6678 {
6679         double index, f;
6680         index = parms[2] + r_refdef.scene.time * parms[3];
6681         index -= floor(index);
6682         switch (func)
6683         {
6684         default:
6685         case Q3WAVEFUNC_NONE:
6686         case Q3WAVEFUNC_NOISE:
6687         case Q3WAVEFUNC_COUNT:
6688                 f = 0;
6689                 break;
6690         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
6691         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
6692         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
6693         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
6694         case Q3WAVEFUNC_TRIANGLE:
6695                 index *= 4;
6696                 f = index - floor(index);
6697                 if (index < 1)
6698                         f = f;
6699                 else if (index < 2)
6700                         f = 1 - f;
6701                 else if (index < 3)
6702                         f = -f;
6703                 else
6704                         f = -(1 - f);
6705                 break;
6706         }
6707         return (float)(parms[0] + parms[1] * f);
6708 }
6709
6710 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
6711 {
6712         int w, h, idx;
6713         float f;
6714         float tcmat[12];
6715         matrix4x4_t matrix, temp;
6716         switch(tcmod->tcmod)
6717         {
6718                 case Q3TCMOD_COUNT:
6719                 case Q3TCMOD_NONE:
6720                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6721                                 matrix = r_waterscrollmatrix;
6722                         else
6723                                 matrix = identitymatrix;
6724                         break;
6725                 case Q3TCMOD_ENTITYTRANSLATE:
6726                         // this is used in Q3 to allow the gamecode to control texcoord
6727                         // scrolling on the entity, which is not supported in darkplaces yet.
6728                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
6729                         break;
6730                 case Q3TCMOD_ROTATE:
6731                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
6732                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
6733                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
6734                         break;
6735                 case Q3TCMOD_SCALE:
6736                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
6737                         break;
6738                 case Q3TCMOD_SCROLL:
6739                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
6740                         break;
6741                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
6742                         w = (int) tcmod->parms[0];
6743                         h = (int) tcmod->parms[1];
6744                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
6745                         f = f - floor(f);
6746                         idx = (int) floor(f * w * h);
6747                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
6748                         break;
6749                 case Q3TCMOD_STRETCH:
6750                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
6751                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
6752                         break;
6753                 case Q3TCMOD_TRANSFORM:
6754                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
6755                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
6756                         VectorSet(tcmat +  6, 0                   , 0                , 1);
6757                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
6758                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
6759                         break;
6760                 case Q3TCMOD_TURBULENT:
6761                         // this is handled in the RSurf_PrepareVertices function
6762                         matrix = identitymatrix;
6763                         break;
6764         }
6765         temp = *texmatrix;
6766         Matrix4x4_Concat(texmatrix, &matrix, &temp);
6767 }
6768
6769 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
6770 {
6771         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
6772         char name[MAX_QPATH];
6773         skinframe_t *skinframe;
6774         unsigned char pixels[296*194];
6775         strlcpy(cache->name, skinname, sizeof(cache->name));
6776         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6777         if (developer_loading.integer)
6778                 Con_Printf("loading %s\n", name);
6779         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6780         if (!skinframe || !skinframe->base)
6781         {
6782                 unsigned char *f;
6783                 fs_offset_t filesize;
6784                 skinframe = NULL;
6785                 f = FS_LoadFile(name, tempmempool, true, &filesize);
6786                 if (f)
6787                 {
6788                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
6789                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6790                         Mem_Free(f);
6791                 }
6792         }
6793         cache->skinframe = skinframe;
6794 }
6795
6796 texture_t *R_GetCurrentTexture(texture_t *t)
6797 {
6798         int i;
6799         const entity_render_t *ent = rsurface.entity;
6800         dp_model_t *model = ent->model;
6801         q3shaderinfo_layer_tcmod_t *tcmod;
6802
6803         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
6804                 return t->currentframe;
6805         t->update_lastrenderframe = r_frame;
6806         t->update_lastrenderentity = (void *)ent;
6807
6808         // switch to an alternate material if this is a q1bsp animated material
6809         {
6810                 texture_t *texture = t;
6811                 int s = rsurface.ent_skinnum;
6812                 if ((unsigned int)s >= (unsigned int)model->numskins)
6813                         s = 0;
6814                 if (model->skinscenes)
6815                 {
6816                         if (model->skinscenes[s].framecount > 1)
6817                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6818                         else
6819                                 s = model->skinscenes[s].firstframe;
6820                 }
6821                 if (s > 0)
6822                         t = t + s * model->num_surfaces;
6823                 if (t->animated)
6824                 {
6825                         // use an alternate animation if the entity's frame is not 0,
6826                         // and only if the texture has an alternate animation
6827                         if (rsurface.ent_alttextures && t->anim_total[1])
6828                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6829                         else
6830                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6831                 }
6832                 texture->currentframe = t;
6833         }
6834
6835         // update currentskinframe to be a qw skin or animation frame
6836         if (rsurface.ent_qwskin >= 0)
6837         {
6838                 i = rsurface.ent_qwskin;
6839                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6840                 {
6841                         r_qwskincache_size = cl.maxclients;
6842                         if (r_qwskincache)
6843                                 Mem_Free(r_qwskincache);
6844                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6845                 }
6846                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6847                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6848                 t->currentskinframe = r_qwskincache[i].skinframe;
6849                 if (t->currentskinframe == NULL)
6850                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6851         }
6852         else if (t->numskinframes >= 2)
6853                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6854         if (t->backgroundnumskinframes >= 2)
6855                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6856
6857         t->currentmaterialflags = t->basematerialflags;
6858         t->currentalpha = rsurface.colormod[3];
6859         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6860                 t->currentalpha *= r_wateralpha.value;
6861         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6862                 t->currentalpha *= t->r_water_wateralpha;
6863         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6864                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6865         if (!(rsurface.ent_flags & RENDER_LIGHT))
6866                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6867         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6868         {
6869                 // pick a model lighting mode
6870                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6871                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6872                 else
6873                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6874         }
6875         if (rsurface.ent_flags & RENDER_ADDITIVE)
6876                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6877         else if (t->currentalpha < 1)
6878                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6879         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6880                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6881         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6882                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6883         if (t->backgroundnumskinframes)
6884                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6885         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6886         {
6887                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6888                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6889         }
6890         else
6891                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6892         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6893                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6894
6895         // there is no tcmod
6896         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6897         {
6898                 t->currenttexmatrix = r_waterscrollmatrix;
6899                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6900         }
6901         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6902         {
6903                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6904                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6905         }
6906
6907         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6908                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6909         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6910                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6911
6912         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6913         if (t->currentskinframe->qpixels)
6914                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6915         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6916         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
6917         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
6918         t->nmaptexture = t->currentskinframe->nmap;
6919         t->glosstexture = r_texture_black;
6920         t->glowtexture = t->currentskinframe->glow;
6921         t->fogtexture = t->currentskinframe->fog;
6922         if (t->backgroundnumskinframes)
6923         {
6924                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
6925                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
6926                 t->backgroundglosstexture = r_texture_black;
6927                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
6928         }
6929         else
6930         {
6931                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6932                 t->backgroundnmaptexture = r_texture_blanknormalmap;
6933                 t->backgroundglosstexture = r_texture_black;
6934                 t->backgroundglowtexture = NULL;
6935         }
6936         t->specularpower = r_shadow_glossexponent.value;
6937         // TODO: store reference values for these in the texture?
6938         t->specularscale = 0;
6939         if (r_shadow_gloss.integer > 0)
6940         {
6941                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6942                 {
6943                         if (r_shadow_glossintensity.value > 0)
6944                         {
6945                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6946                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6947                                 t->specularscale = r_shadow_glossintensity.value;
6948                         }
6949                 }
6950                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6951                 {
6952                         t->glosstexture = r_texture_white;
6953                         t->backgroundglosstexture = r_texture_white;
6954                         t->specularscale = r_shadow_gloss2intensity.value;
6955                         t->specularpower = r_shadow_gloss2exponent.value;
6956                 }
6957         }
6958         t->specularscale *= t->specularscalemod;
6959         t->specularpower *= t->specularpowermod;
6960
6961         // lightmaps mode looks bad with dlights using actual texturing, so turn
6962         // off the colormap and glossmap, but leave the normalmap on as it still
6963         // accurately represents the shading involved
6964         if (gl_lightmaps.integer)
6965         {
6966                 t->basetexture = r_texture_grey128;
6967                 t->pantstexture = r_texture_black;
6968                 t->shirttexture = r_texture_black;
6969                 t->nmaptexture = r_texture_blanknormalmap;
6970                 t->glosstexture = r_texture_black;
6971                 t->glowtexture = NULL;
6972                 t->fogtexture = NULL;
6973                 t->backgroundbasetexture = NULL;
6974                 t->backgroundnmaptexture = r_texture_blanknormalmap;
6975                 t->backgroundglosstexture = r_texture_black;
6976                 t->backgroundglowtexture = NULL;
6977                 t->specularscale = 0;
6978                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6979         }
6980
6981         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
6982         VectorClear(t->dlightcolor);
6983         t->currentnumlayers = 0;
6984         if (t->currentmaterialflags & MATERIALFLAG_WALL)
6985         {
6986                 int blendfunc1, blendfunc2;
6987                 qboolean depthmask;
6988                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6989                 {
6990                         blendfunc1 = GL_SRC_ALPHA;
6991                         blendfunc2 = GL_ONE;
6992                 }
6993                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6994                 {
6995                         blendfunc1 = GL_SRC_ALPHA;
6996                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6997                 }
6998                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6999                 {
7000                         blendfunc1 = t->customblendfunc[0];
7001                         blendfunc2 = t->customblendfunc[1];
7002                 }
7003                 else
7004                 {
7005                         blendfunc1 = GL_ONE;
7006                         blendfunc2 = GL_ZERO;
7007                 }
7008                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7009                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7010                 {
7011                         // fullbright is not affected by r_refdef.lightmapintensity
7012                         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]);
7013                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7014                                 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]);
7015                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7016                                 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]);
7017                 }
7018                 else
7019                 {
7020                         vec3_t ambientcolor;
7021                         float colorscale;
7022                         // set the color tint used for lights affecting this surface
7023                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7024                         colorscale = 2;
7025                         // q3bsp has no lightmap updates, so the lightstylevalue that
7026                         // would normally be baked into the lightmap must be
7027                         // applied to the color
7028                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7029                         if (model->type == mod_brushq3)
7030                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7031                         colorscale *= r_refdef.lightmapintensity;
7032                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7033                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7034                         // basic lit geometry
7035                         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]);
7036                         // add pants/shirt if needed
7037                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7038                                 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]);
7039                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7040                                 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]);
7041                         // now add ambient passes if needed
7042                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7043                         {
7044                                 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]);
7045                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7046                                         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]);
7047                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7048                                         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]);
7049                         }
7050                 }
7051                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7052                         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]);
7053                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7054                 {
7055                         // if this is opaque use alpha blend which will darken the earlier
7056                         // passes cheaply.
7057                         //
7058                         // if this is an alpha blended material, all the earlier passes
7059                         // were darkened by fog already, so we only need to add the fog
7060                         // color ontop through the fog mask texture
7061                         //
7062                         // if this is an additive blended material, all the earlier passes
7063                         // were darkened by fog already, and we should not add fog color
7064                         // (because the background was not darkened, there is no fog color
7065                         // that was lost behind it).
7066                         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]);
7067                 }
7068         }
7069
7070         return t->currentframe;
7071 }
7072
7073 rsurfacestate_t rsurface;
7074
7075 void R_Mesh_ResizeArrays(int newvertices)
7076 {
7077         float *base;
7078         if (rsurface.array_size >= newvertices)
7079                 return;
7080         if (rsurface.array_modelvertex3f)
7081                 Mem_Free(rsurface.array_modelvertex3f);
7082         rsurface.array_size = (newvertices + 1023) & ~1023;
7083         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
7084         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
7085         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
7086         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
7087         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
7088         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
7089         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
7090         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
7091         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
7092         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
7093         rsurface.array_color4f           = base + rsurface.array_size * 27;
7094         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
7095 }
7096
7097 void RSurf_ActiveWorldEntity(void)
7098 {
7099         dp_model_t *model = r_refdef.scene.worldmodel;
7100         //if (rsurface.entity == r_refdef.scene.worldentity)
7101         //      return;
7102         rsurface.entity = r_refdef.scene.worldentity;
7103         rsurface.skeleton = NULL;
7104         rsurface.ent_skinnum = 0;
7105         rsurface.ent_qwskin = -1;
7106         rsurface.ent_shadertime = 0;
7107         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7108         if (rsurface.array_size < model->surfmesh.num_vertices)
7109                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
7110         rsurface.matrix = identitymatrix;
7111         rsurface.inversematrix = identitymatrix;
7112         rsurface.matrixscale = 1;
7113         rsurface.inversematrixscale = 1;
7114         R_EntityMatrix(&identitymatrix);
7115         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7116         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7117         rsurface.fograngerecip = r_refdef.fograngerecip;
7118         rsurface.fogheightfade = r_refdef.fogheightfade;
7119         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7120         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7121         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7122         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7123         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7124         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7125         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7126         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7127         rsurface.colormod[3] = 1;
7128         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);
7129         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7130         rsurface.frameblend[0].lerp = 1;
7131         rsurface.ent_alttextures = false;
7132         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7133         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7134         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7135         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
7136         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7137         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7138         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
7139         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7140         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7141         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
7142         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7143         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7144         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
7145         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7146         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7147         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
7148         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7149         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7150         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
7151         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7152         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7153         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
7154         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7155         rsurface.modelelement3i = model->surfmesh.data_element3i;
7156         rsurface.modelelement3s = model->surfmesh.data_element3s;
7157         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
7158         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
7159         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7160         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
7161         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
7162         rsurface.modelsurfaces = model->data_surfaces;
7163         rsurface.generatedvertex = false;
7164         rsurface.vertex3f  = rsurface.modelvertex3f;
7165         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7166         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7167         rsurface.svector3f = rsurface.modelsvector3f;
7168         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7169         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7170         rsurface.tvector3f = rsurface.modeltvector3f;
7171         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7172         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7173         rsurface.normal3f  = rsurface.modelnormal3f;
7174         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7175         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7176         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7177 }
7178
7179 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7180 {
7181         dp_model_t *model = ent->model;
7182         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7183         //      return;
7184         rsurface.entity = (entity_render_t *)ent;
7185         rsurface.skeleton = ent->skeleton;
7186         rsurface.ent_skinnum = ent->skinnum;
7187         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;
7188         rsurface.ent_shadertime = ent->shadertime;
7189         rsurface.ent_flags = ent->flags;
7190         if (rsurface.array_size < model->surfmesh.num_vertices)
7191                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
7192         rsurface.matrix = ent->matrix;
7193         rsurface.inversematrix = ent->inversematrix;
7194         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7195         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7196         R_EntityMatrix(&rsurface.matrix);
7197         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7198         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7199         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7200         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7201         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7202         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7203         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7204         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7205         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7206         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7207         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7208         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7209         rsurface.colormod[3] = ent->alpha;
7210         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7211         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7212         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7213         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7214         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7215         if (ent->model->brush.submodel && !prepass)
7216         {
7217                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7218                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7219         }
7220         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7221         {
7222                 if (ent->animcache_vertex3f && !r_framedata_failed)
7223                 {
7224                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7225                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7226                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7227                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7228                 }
7229                 else if (wanttangents)
7230                 {
7231                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7232                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
7233                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
7234                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7235                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
7236                 }
7237                 else if (wantnormals)
7238                 {
7239                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7240                         rsurface.modelsvector3f = NULL;
7241                         rsurface.modeltvector3f = NULL;
7242                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7243                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
7244                 }
7245                 else
7246                 {
7247                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7248                         rsurface.modelsvector3f = NULL;
7249                         rsurface.modeltvector3f = NULL;
7250                         rsurface.modelnormal3f = NULL;
7251                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
7252                 }
7253                 rsurface.modelvertex3f_bufferobject = 0;
7254                 rsurface.modelvertex3f_bufferoffset = 0;
7255                 rsurface.modelsvector3f_bufferobject = 0;
7256                 rsurface.modelsvector3f_bufferoffset = 0;
7257                 rsurface.modeltvector3f_bufferobject = 0;
7258                 rsurface.modeltvector3f_bufferoffset = 0;
7259                 rsurface.modelnormal3f_bufferobject = 0;
7260                 rsurface.modelnormal3f_bufferoffset = 0;
7261                 rsurface.generatedvertex = true;
7262         }
7263         else
7264         {
7265                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7266                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
7267                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7268                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7269                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
7270                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7271                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7272                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
7273                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7274                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7275                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
7276                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7277                 rsurface.generatedvertex = false;
7278         }
7279         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7280         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
7281         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7282         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7283         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
7284         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7285         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7286         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
7287         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7288         rsurface.modelelement3i = model->surfmesh.data_element3i;
7289         rsurface.modelelement3s = model->surfmesh.data_element3s;
7290         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
7291         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
7292         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7293         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
7294         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
7295         rsurface.modelsurfaces = model->data_surfaces;
7296         rsurface.vertex3f  = rsurface.modelvertex3f;
7297         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7298         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7299         rsurface.svector3f = rsurface.modelsvector3f;
7300         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7301         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7302         rsurface.tvector3f = rsurface.modeltvector3f;
7303         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7304         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7305         rsurface.normal3f  = rsurface.modelnormal3f;
7306         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7307         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7308         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7309 }
7310
7311 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)
7312 {
7313         rsurface.entity = r_refdef.scene.worldentity;
7314         rsurface.skeleton = NULL;
7315         rsurface.ent_skinnum = 0;
7316         rsurface.ent_qwskin = -1;
7317         rsurface.ent_shadertime = shadertime;
7318         rsurface.ent_flags = entflags;
7319         rsurface.modelnum_vertices = numvertices;
7320         rsurface.modelnum_triangles = numtriangles;
7321         if (rsurface.array_size < rsurface.modelnum_vertices)
7322                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
7323         rsurface.matrix = *matrix;
7324         rsurface.inversematrix = *inversematrix;
7325         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7326         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7327         R_EntityMatrix(&rsurface.matrix);
7328         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7329         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7330         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7331         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7332         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7333         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7334         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7335         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7336         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7337         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7338         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7339         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7340         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);
7341         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7342         rsurface.frameblend[0].lerp = 1;
7343         rsurface.ent_alttextures = false;
7344         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7345         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7346         if (wanttangents)
7347         {
7348                 rsurface.modelvertex3f = vertex3f;
7349                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
7350                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
7351                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
7352         }
7353         else if (wantnormals)
7354         {
7355                 rsurface.modelvertex3f = vertex3f;
7356                 rsurface.modelsvector3f = NULL;
7357                 rsurface.modeltvector3f = NULL;
7358                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
7359         }
7360         else
7361         {
7362                 rsurface.modelvertex3f = vertex3f;
7363                 rsurface.modelsvector3f = NULL;
7364                 rsurface.modeltvector3f = NULL;
7365                 rsurface.modelnormal3f = NULL;
7366         }
7367         rsurface.modelvertex3f_bufferobject = 0;
7368         rsurface.modelvertex3f_bufferoffset = 0;
7369         rsurface.modelsvector3f_bufferobject = 0;
7370         rsurface.modelsvector3f_bufferoffset = 0;
7371         rsurface.modeltvector3f_bufferobject = 0;
7372         rsurface.modeltvector3f_bufferoffset = 0;
7373         rsurface.modelnormal3f_bufferobject = 0;
7374         rsurface.modelnormal3f_bufferoffset = 0;
7375         rsurface.generatedvertex = true;
7376         rsurface.modellightmapcolor4f  = color4f;
7377         rsurface.modellightmapcolor4f_bufferobject = 0;
7378         rsurface.modellightmapcolor4f_bufferoffset = 0;
7379         rsurface.modeltexcoordtexture2f  = texcoord2f;
7380         rsurface.modeltexcoordtexture2f_bufferobject = 0;
7381         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7382         rsurface.modeltexcoordlightmap2f  = NULL;
7383         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
7384         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7385         rsurface.modelelement3i = element3i;
7386         rsurface.modelelement3s = element3s;
7387         rsurface.modelelement3i_bufferobject = 0;
7388         rsurface.modelelement3s_bufferobject = 0;
7389         rsurface.modellightmapoffsets = NULL;
7390         rsurface.modelsurfaces = NULL;
7391         rsurface.vertex3f  = rsurface.modelvertex3f;
7392         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7393         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7394         rsurface.svector3f = rsurface.modelsvector3f;
7395         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7396         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7397         rsurface.tvector3f = rsurface.modeltvector3f;
7398         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7399         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7400         rsurface.normal3f  = rsurface.modelnormal3f;
7401         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7402         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7403         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7404
7405         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
7406         {
7407                 if ((wantnormals || wanttangents) && !normal3f)
7408                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7409                 if (wanttangents && !svector3f)
7410                         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);
7411         }
7412 }
7413
7414 float RSurf_FogPoint(const float *v)
7415 {
7416         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7417         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7418         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7419         float FogHeightFade = r_refdef.fogheightfade;
7420         float fogfrac;
7421         unsigned int fogmasktableindex;
7422         if (r_refdef.fogplaneviewabove)
7423                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7424         else
7425                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7426         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7427         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7428 }
7429
7430 float RSurf_FogVertex(const float *v)
7431 {
7432         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7433         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7434         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7435         float FogHeightFade = rsurface.fogheightfade;
7436         float fogfrac;
7437         unsigned int fogmasktableindex;
7438         if (r_refdef.fogplaneviewabove)
7439                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7440         else
7441                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7442         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7443         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7444 }
7445
7446 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
7447 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
7448 {
7449         int deformindex;
7450         int texturesurfaceindex;
7451         int i, j;
7452         float amplitude;
7453         float animpos;
7454         float scale;
7455         const float *v1, *in_tc;
7456         float *out_tc;
7457         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
7458         float waveparms[4];
7459         q3shaderinfo_deform_t *deform;
7460         // 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
7461         if (rsurface.generatedvertex)
7462         {
7463                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
7464                         generatenormals = true;
7465                 for (i = 0;i < Q3MAXDEFORMS;i++)
7466                 {
7467                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
7468                         {
7469                                 generatetangents = true;
7470                                 generatenormals = true;
7471                         }
7472                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
7473                                 generatenormals = true;
7474                 }
7475                 if (generatenormals && !rsurface.modelnormal3f)
7476                 {
7477                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7478                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
7479                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
7480                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7481                 }
7482                 if (generatetangents && !rsurface.modelsvector3f)
7483                 {
7484                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
7485                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
7486                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
7487                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
7488                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
7489                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
7490                         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);
7491                 }
7492         }
7493         rsurface.vertex3f  = rsurface.modelvertex3f;
7494         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7495         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7496         rsurface.svector3f = rsurface.modelsvector3f;
7497         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7498         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7499         rsurface.tvector3f = rsurface.modeltvector3f;
7500         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7501         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7502         rsurface.normal3f  = rsurface.modelnormal3f;
7503         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7504         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7505         // if vertices are deformed (sprite flares and things in maps, possibly
7506         // water waves, bulges and other deformations), generate them into
7507         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
7508         // (may be static model data or generated data for an animated model, or
7509         //  the previous deform pass)
7510         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
7511         {
7512                 switch (deform->deform)
7513                 {
7514                 default:
7515                 case Q3DEFORM_PROJECTIONSHADOW:
7516                 case Q3DEFORM_TEXT0:
7517                 case Q3DEFORM_TEXT1:
7518                 case Q3DEFORM_TEXT2:
7519                 case Q3DEFORM_TEXT3:
7520                 case Q3DEFORM_TEXT4:
7521                 case Q3DEFORM_TEXT5:
7522                 case Q3DEFORM_TEXT6:
7523                 case Q3DEFORM_TEXT7:
7524                 case Q3DEFORM_NONE:
7525                         break;
7526                 case Q3DEFORM_AUTOSPRITE:
7527                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
7528                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
7529                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
7530                         VectorNormalize(newforward);
7531                         VectorNormalize(newright);
7532                         VectorNormalize(newup);
7533                         // make deformed versions of only the model vertices used by the specified surfaces
7534                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7535                         {
7536                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7537                                 // a single autosprite surface can contain multiple sprites...
7538                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
7539                                 {
7540                                         VectorClear(center);
7541                                         for (i = 0;i < 4;i++)
7542                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
7543                                         VectorScale(center, 0.25f, center);
7544                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
7545                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
7546                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
7547                                         for (i = 0;i < 4;i++)
7548                                         {
7549                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
7550                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
7551                                         }
7552                                 }
7553                                 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);
7554                                 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);
7555                         }
7556                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7557                         rsurface.vertex3f_bufferobject = 0;
7558                         rsurface.vertex3f_bufferoffset = 0;
7559                         rsurface.svector3f = rsurface.array_deformedsvector3f;
7560                         rsurface.svector3f_bufferobject = 0;
7561                         rsurface.svector3f_bufferoffset = 0;
7562                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
7563                         rsurface.tvector3f_bufferobject = 0;
7564                         rsurface.tvector3f_bufferoffset = 0;
7565                         rsurface.normal3f = rsurface.array_deformednormal3f;
7566                         rsurface.normal3f_bufferobject = 0;
7567                         rsurface.normal3f_bufferoffset = 0;
7568                         break;
7569                 case Q3DEFORM_AUTOSPRITE2:
7570                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
7571                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
7572                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
7573                         VectorNormalize(newforward);
7574                         VectorNormalize(newright);
7575                         VectorNormalize(newup);
7576                         // make deformed versions of only the model vertices used by the specified surfaces
7577                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7578                         {
7579                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7580                                 const float *v1, *v2;
7581                                 vec3_t start, end;
7582                                 float f, l;
7583                                 struct
7584                                 {
7585                                         float length2;
7586                                         const float *v1;
7587                                         const float *v2;
7588                                 }
7589                                 shortest[2];
7590                                 memset(shortest, 0, sizeof(shortest));
7591                                 // a single autosprite surface can contain multiple sprites...
7592                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
7593                                 {
7594                                         VectorClear(center);
7595                                         for (i = 0;i < 4;i++)
7596                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
7597                                         VectorScale(center, 0.25f, center);
7598                                         // find the two shortest edges, then use them to define the
7599                                         // axis vectors for rotating around the central axis
7600                                         for (i = 0;i < 6;i++)
7601                                         {
7602                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
7603                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
7604 #if 0
7605                                                 Debug_PolygonBegin(NULL, 0);
7606                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
7607                                                 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);
7608                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
7609                                                 Debug_PolygonEnd();
7610 #endif
7611                                                 l = VectorDistance2(v1, v2);
7612                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
7613                                                 if (v1[2] != v2[2])
7614                                                         l += (1.0f / 1024.0f);
7615                                                 if (shortest[0].length2 > l || i == 0)
7616                                                 {
7617                                                         shortest[1] = shortest[0];
7618                                                         shortest[0].length2 = l;
7619                                                         shortest[0].v1 = v1;
7620                                                         shortest[0].v2 = v2;
7621                                                 }
7622                                                 else if (shortest[1].length2 > l || i == 1)
7623                                                 {
7624                                                         shortest[1].length2 = l;
7625                                                         shortest[1].v1 = v1;
7626                                                         shortest[1].v2 = v2;
7627                                                 }
7628                                         }
7629                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
7630                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
7631 #if 0
7632                                         Debug_PolygonBegin(NULL, 0);
7633                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
7634                                         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);
7635                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
7636                                         Debug_PolygonEnd();
7637 #endif
7638                                         // this calculates the right vector from the shortest edge
7639                                         // and the up vector from the edge midpoints
7640                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
7641                                         VectorNormalize(right);
7642                                         VectorSubtract(end, start, up);
7643                                         VectorNormalize(up);
7644                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
7645                                         VectorSubtract(rsurface.localvieworigin, center, forward);
7646                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
7647                                         VectorNegate(forward, forward);
7648                                         VectorReflect(forward, 0, up, forward);
7649                                         VectorNormalize(forward);
7650                                         CrossProduct(up, forward, newright);
7651                                         VectorNormalize(newright);
7652 #if 0
7653                                         Debug_PolygonBegin(NULL, 0);
7654                                         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);
7655                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
7656                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
7657                                         Debug_PolygonEnd();
7658 #endif
7659 #if 0
7660                                         Debug_PolygonBegin(NULL, 0);
7661                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
7662                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
7663                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
7664                                         Debug_PolygonEnd();
7665 #endif
7666                                         // rotate the quad around the up axis vector, this is made
7667                                         // especially easy by the fact we know the quad is flat,
7668                                         // so we only have to subtract the center position and
7669                                         // measure distance along the right vector, and then
7670                                         // multiply that by the newright vector and add back the
7671                                         // center position
7672                                         // we also need to subtract the old position to undo the
7673                                         // displacement from the center, which we do with a
7674                                         // DotProduct, the subtraction/addition of center is also
7675                                         // optimized into DotProducts here
7676                                         l = DotProduct(right, center);
7677                                         for (i = 0;i < 4;i++)
7678                                         {
7679                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
7680                                                 f = DotProduct(right, v1) - l;
7681                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
7682                                         }
7683                                 }
7684                                 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);
7685                                 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);
7686                         }
7687                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7688                         rsurface.vertex3f_bufferobject = 0;
7689                         rsurface.vertex3f_bufferoffset = 0;
7690                         rsurface.svector3f = rsurface.array_deformedsvector3f;
7691                         rsurface.svector3f_bufferobject = 0;
7692                         rsurface.svector3f_bufferoffset = 0;
7693                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
7694                         rsurface.tvector3f_bufferobject = 0;
7695                         rsurface.tvector3f_bufferoffset = 0;
7696                         rsurface.normal3f = rsurface.array_deformednormal3f;
7697                         rsurface.normal3f_bufferobject = 0;
7698                         rsurface.normal3f_bufferoffset = 0;
7699                         break;
7700                 case Q3DEFORM_NORMAL:
7701                         // deform the normals to make reflections wavey
7702                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7703                         {
7704                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7705                                 for (j = 0;j < surface->num_vertices;j++)
7706                                 {
7707                                         float vertex[3];
7708                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
7709                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
7710                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
7711                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7712                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7713                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7714                                         VectorNormalize(normal);
7715                                 }
7716                                 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);
7717                         }
7718                         rsurface.svector3f = rsurface.array_deformedsvector3f;
7719                         rsurface.svector3f_bufferobject = 0;
7720                         rsurface.svector3f_bufferoffset = 0;
7721                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
7722                         rsurface.tvector3f_bufferobject = 0;
7723                         rsurface.tvector3f_bufferoffset = 0;
7724                         rsurface.normal3f = rsurface.array_deformednormal3f;
7725                         rsurface.normal3f_bufferobject = 0;
7726                         rsurface.normal3f_bufferoffset = 0;
7727                         break;
7728                 case Q3DEFORM_WAVE:
7729                         // deform vertex array to make wavey water and flags and such
7730                         waveparms[0] = deform->waveparms[0];
7731                         waveparms[1] = deform->waveparms[1];
7732                         waveparms[2] = deform->waveparms[2];
7733                         waveparms[3] = deform->waveparms[3];
7734                         // this is how a divisor of vertex influence on deformation
7735                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
7736                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
7737                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7738                         {
7739                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7740                                 for (j = 0;j < surface->num_vertices;j++)
7741                                 {
7742                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
7743                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
7744                                         // if the wavefunc depends on time, evaluate it per-vertex
7745                                         if (waveparms[3])
7746                                         {
7747                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
7748                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
7749                                         }
7750                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
7751                                 }
7752                         }
7753                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7754                         rsurface.vertex3f_bufferobject = 0;
7755                         rsurface.vertex3f_bufferoffset = 0;
7756                         break;
7757                 case Q3DEFORM_BULGE:
7758                         // deform vertex array to make the surface have moving bulges
7759                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7760                         {
7761                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7762                                 for (j = 0;j < surface->num_vertices;j++)
7763                                 {
7764                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
7765                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
7766                                 }
7767                         }
7768                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7769                         rsurface.vertex3f_bufferobject = 0;
7770                         rsurface.vertex3f_bufferoffset = 0;
7771                         break;
7772                 case Q3DEFORM_MOVE:
7773                         // deform vertex array
7774                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
7775                         VectorScale(deform->parms, scale, waveparms);
7776                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7777                         {
7778                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7779                                 for (j = 0;j < surface->num_vertices;j++)
7780                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
7781                         }
7782                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7783                         rsurface.vertex3f_bufferobject = 0;
7784                         rsurface.vertex3f_bufferoffset = 0;
7785                         break;
7786                 }
7787         }
7788         // generate texcoords based on the chosen texcoord source
7789         switch(rsurface.texture->tcgen.tcgen)
7790         {
7791         default:
7792         case Q3TCGEN_TEXTURE:
7793                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
7794                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
7795                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
7796                 break;
7797         case Q3TCGEN_LIGHTMAP:
7798                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
7799                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
7800                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
7801                 break;
7802         case Q3TCGEN_VECTOR:
7803                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7804                 {
7805                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7806                         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)
7807                         {
7808                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
7809                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
7810                         }
7811                 }
7812                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7813                 rsurface.texcoordtexture2f_bufferobject  = 0;
7814                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7815                 break;
7816         case Q3TCGEN_ENVIRONMENT:
7817                 // make environment reflections using a spheremap
7818                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7819                 {
7820                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7821                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
7822                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
7823                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
7824                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
7825                         {
7826                                 // identical to Q3A's method, but executed in worldspace so
7827                                 // carried models can be shiny too
7828
7829                                 float viewer[3], d, reflected[3], worldreflected[3];
7830
7831                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
7832                                 // VectorNormalize(viewer);
7833
7834                                 d = DotProduct(normal, viewer);
7835
7836                                 reflected[0] = normal[0]*2*d - viewer[0];
7837                                 reflected[1] = normal[1]*2*d - viewer[1];
7838                                 reflected[2] = normal[2]*2*d - viewer[2];
7839                                 // note: this is proportinal to viewer, so we can normalize later
7840
7841                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7842                                 VectorNormalize(worldreflected);
7843
7844                                 // note: this sphere map only uses world x and z!
7845                                 // so positive and negative y will LOOK THE SAME.
7846                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7847                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7848                         }
7849                 }
7850                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7851                 rsurface.texcoordtexture2f_bufferobject  = 0;
7852                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7853                 break;
7854         }
7855         // the only tcmod that needs software vertex processing is turbulent, so
7856         // check for it here and apply the changes if needed
7857         // and we only support that as the first one
7858         // (handling a mixture of turbulent and other tcmods would be problematic
7859         //  without punting it entirely to a software path)
7860         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7861         {
7862                 amplitude = rsurface.texture->tcmods[0].parms[1];
7863                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7864                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7865                 {
7866                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7867                         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)
7868                         {
7869                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7870                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7871                         }
7872                 }
7873                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7874                 rsurface.texcoordtexture2f_bufferobject  = 0;
7875                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7876         }
7877         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
7878         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7879         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7880         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7881 }
7882
7883 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7884 {
7885         int i, j;
7886         const msurface_t *surface = texturesurfacelist[0];
7887         const msurface_t *surface2;
7888         int firstvertex;
7889         int endvertex;
7890         int numvertices;
7891         int numtriangles;
7892         // TODO: lock all array ranges before render, rather than on each surface
7893         if (texturenumsurfaces == 1)
7894         {
7895                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7896                 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);
7897         }
7898         else if (r_batchmode.integer == 2)
7899         {
7900                 #define MAXBATCHTRIANGLES 4096
7901                 int batchtriangles = 0;
7902                 static int batchelements[MAXBATCHTRIANGLES*3];
7903                 for (i = 0;i < texturenumsurfaces;i = j)
7904                 {
7905                         surface = texturesurfacelist[i];
7906                         j = i + 1;
7907                         if (surface->num_triangles > MAXBATCHTRIANGLES)
7908                         {
7909                                 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);
7910                                 continue;
7911                         }
7912                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7913                         batchtriangles = surface->num_triangles;
7914                         firstvertex = surface->num_firstvertex;
7915                         endvertex = surface->num_firstvertex + surface->num_vertices;
7916                         for (;j < texturenumsurfaces;j++)
7917                         {
7918                                 surface2 = texturesurfacelist[j];
7919                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7920                                         break;
7921                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7922                                 batchtriangles += surface2->num_triangles;
7923                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
7924                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7925                         }
7926                         surface2 = texturesurfacelist[j-1];
7927                         numvertices = endvertex - firstvertex;
7928                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7929                 }
7930         }
7931         else if (r_batchmode.integer == 1)
7932         {
7933                 for (i = 0;i < texturenumsurfaces;i = j)
7934                 {
7935                         surface = texturesurfacelist[i];
7936                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7937                                 if (texturesurfacelist[j] != surface2)
7938                                         break;
7939                         surface2 = texturesurfacelist[j-1];
7940                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7941                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7942                         GL_LockArrays(surface->num_firstvertex, numvertices);
7943                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7944                 }
7945         }
7946         else
7947         {
7948                 for (i = 0;i < texturenumsurfaces;i++)
7949                 {
7950                         surface = texturesurfacelist[i];
7951                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7952                         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);
7953                 }
7954         }
7955 }
7956
7957 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
7958 {
7959         switch(vid.renderpath)
7960         {
7961         case RENDERPATH_CGGL:
7962 #ifdef SUPPORTCG
7963                 if (r_cg_permutation->fp_Texture_Lightmap ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Lightmap , R_GetTexture(surface->lightmaptexture ));
7964                 if (r_cg_permutation->fp_Texture_Deluxemap) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Deluxemap, R_GetTexture(surface->deluxemaptexture));
7965 #endif
7966                 break;
7967         case RENDERPATH_GL20:
7968                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(surface->lightmaptexture ));
7969                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, R_GetTexture(surface->deluxemaptexture));
7970                 break;
7971         case RENDERPATH_GL13:
7972         case RENDERPATH_GL11:
7973                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
7974                 break;
7975         }
7976 }
7977
7978 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
7979 {
7980         // pick the closest matching water plane and bind textures
7981         int planeindex, vertexindex;
7982         float d, bestd;
7983         vec3_t vert;
7984         const float *v;
7985         r_waterstate_waterplane_t *p, *bestp;
7986         bestd = 0;
7987         bestp = NULL;
7988         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7989         {
7990                 d = 0;
7991                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7992                 {
7993                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
7994                         d += fabs(PlaneDiff(vert, &p->plane));
7995                 }
7996                 if (bestd > d || !bestp)
7997                 {
7998                         bestd = d;
7999                         bestp = p;
8000                 }
8001         }
8002         switch(vid.renderpath)
8003         {
8004         case RENDERPATH_CGGL:
8005 #ifdef SUPPORTCG
8006                 if (r_cg_permutation->fp_Texture_Refraction >= 0) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Refraction, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));
8007                 if (r_cg_permutation->fp_Texture_Reflection >= 0) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Reflection, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));
8008 #endif
8009                 break;
8010         case RENDERPATH_GL20:
8011                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));
8012                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));
8013                 break;
8014         case RENDERPATH_GL13:
8015         case RENDERPATH_GL11:
8016                 break;
8017         }
8018 }
8019
8020 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8021 {
8022         int i;
8023         const msurface_t *surface;
8024         if (r_waterstate.renderingscene)
8025                 return;
8026         for (i = 0;i < texturenumsurfaces;i++)
8027         {
8028                 surface = texturesurfacelist[i];
8029                 RSurf_BindLightmapForSurface(surface);
8030                 RSurf_BindReflectionForSurface(surface);
8031                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8032                 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);
8033         }
8034 }
8035
8036 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8037 {
8038         int i;
8039         int j;
8040         const msurface_t *surface = texturesurfacelist[0];
8041         const msurface_t *surface2;
8042         int firstvertex;
8043         int endvertex;
8044         int numvertices;
8045         int numtriangles;
8046         if (texturenumsurfaces == 1)
8047         {
8048                 RSurf_BindLightmapForSurface(surface);
8049                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8050                 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);
8051         }
8052         else if (r_batchmode.integer == 2)
8053         {
8054 #define MAXBATCHTRIANGLES 4096
8055                 int batchtriangles = 0;
8056                 static int batchelements[MAXBATCHTRIANGLES*3];
8057                 for (i = 0;i < texturenumsurfaces;i = j)
8058                 {
8059                         surface = texturesurfacelist[i];
8060                         RSurf_BindLightmapForSurface(surface);
8061                         j = i + 1;
8062                         if (surface->num_triangles > MAXBATCHTRIANGLES)
8063                         {
8064                                 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);
8065                                 continue;
8066                         }
8067                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
8068                         batchtriangles = surface->num_triangles;
8069                         firstvertex = surface->num_firstvertex;
8070                         endvertex = surface->num_firstvertex + surface->num_vertices;
8071                         for (;j < texturenumsurfaces;j++)
8072                         {
8073                                 surface2 = texturesurfacelist[j];
8074                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
8075                                         break;
8076                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
8077                                 batchtriangles += surface2->num_triangles;
8078                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
8079                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
8080                         }
8081                         surface2 = texturesurfacelist[j-1];
8082                         numvertices = endvertex - firstvertex;
8083                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
8084                 }
8085         }
8086         else if (r_batchmode.integer == 1)
8087         {
8088 #if 0
8089                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
8090                 for (i = 0;i < texturenumsurfaces;i = j)
8091                 {
8092                         surface = texturesurfacelist[i];
8093                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
8094                                 if (texturesurfacelist[j] != surface2)
8095                                         break;
8096                         Con_Printf(" %i", j - i);
8097                 }
8098                 Con_Printf("\n");
8099                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
8100 #endif
8101                 for (i = 0;i < texturenumsurfaces;i = j)
8102                 {
8103                         surface = texturesurfacelist[i];
8104                         RSurf_BindLightmapForSurface(surface);
8105                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
8106                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
8107                                         break;
8108 #if 0
8109                         Con_Printf(" %i", j - i);
8110 #endif
8111                         surface2 = texturesurfacelist[j-1];
8112                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
8113                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
8114                         GL_LockArrays(surface->num_firstvertex, numvertices);
8115                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
8116                 }
8117 #if 0
8118                 Con_Printf("\n");
8119 #endif
8120         }
8121         else
8122         {
8123                 for (i = 0;i < texturenumsurfaces;i++)
8124                 {
8125                         surface = texturesurfacelist[i];
8126                         RSurf_BindLightmapForSurface(surface);
8127                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8128                         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);
8129                 }
8130         }
8131 }
8132
8133 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8134 {
8135         int j;
8136         int texturesurfaceindex;
8137         if (r_showsurfaces.integer == 2)
8138         {
8139                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8140                 {
8141                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8142                         for (j = 0;j < surface->num_triangles;j++)
8143                         {
8144                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
8145                                 GL_Color(f, f, f, 1);
8146                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
8147                         }
8148                 }
8149         }
8150         else
8151         {
8152                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8153                 {
8154                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8155                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
8156                         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);
8157                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8158                         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);
8159                 }
8160         }
8161 }
8162
8163 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8164 {
8165         int texturesurfaceindex;
8166         int i;
8167         const float *v;
8168         float *c2;
8169         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8170         {
8171                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8172                 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)
8173                 {
8174                         c2[0] = 0.5;
8175                         c2[1] = 0.5;
8176                         c2[2] = 0.5;
8177                         c2[3] = 1;
8178                 }
8179         }
8180         rsurface.lightmapcolor4f = rsurface.array_color4f;
8181         rsurface.lightmapcolor4f_bufferobject = 0;
8182         rsurface.lightmapcolor4f_bufferoffset = 0;
8183 }
8184
8185 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8186 {
8187         int texturesurfaceindex;
8188         int i;
8189         float f;
8190         const float *v;
8191         const float *c;
8192         float *c2;
8193         if (rsurface.lightmapcolor4f)
8194         {
8195                 // generate color arrays for the surfaces in this list
8196                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8197                 {
8198                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8199                         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)
8200                         {
8201                                 f = RSurf_FogVertex(v);
8202                                 c2[0] = c[0] * f;
8203                                 c2[1] = c[1] * f;
8204                                 c2[2] = c[2] * f;
8205                                 c2[3] = c[3];
8206                         }
8207                 }
8208         }
8209         else
8210         {
8211                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8212                 {
8213                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8214                         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)
8215                         {
8216                                 f = RSurf_FogVertex(v);
8217                                 c2[0] = f;
8218                                 c2[1] = f;
8219                                 c2[2] = f;
8220                                 c2[3] = 1;
8221                         }
8222                 }
8223         }
8224         rsurface.lightmapcolor4f = rsurface.array_color4f;
8225         rsurface.lightmapcolor4f_bufferobject = 0;
8226         rsurface.lightmapcolor4f_bufferoffset = 0;
8227 }
8228
8229 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8230 {
8231         int texturesurfaceindex;
8232         int i;
8233         float f;
8234         const float *v;
8235         const float *c;
8236         float *c2;
8237         if (!rsurface.lightmapcolor4f)
8238                 return;
8239         // generate color arrays for the surfaces in this list
8240         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8241         {
8242                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8243                 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)
8244                 {
8245                         f = RSurf_FogVertex(v);
8246                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8247                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8248                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8249                         c2[3] = c[3];
8250                 }
8251         }
8252         rsurface.lightmapcolor4f = rsurface.array_color4f;
8253         rsurface.lightmapcolor4f_bufferobject = 0;
8254         rsurface.lightmapcolor4f_bufferoffset = 0;
8255 }
8256
8257 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
8258 {
8259         int texturesurfaceindex;
8260         int i;
8261         const float *c;
8262         float *c2;
8263         if (!rsurface.lightmapcolor4f)
8264                 return;
8265         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8266         {
8267                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8268                 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)
8269                 {
8270                         c2[0] = c[0] * r;
8271                         c2[1] = c[1] * g;
8272                         c2[2] = c[2] * b;
8273                         c2[3] = c[3] * a;
8274                 }
8275         }
8276         rsurface.lightmapcolor4f = rsurface.array_color4f;
8277         rsurface.lightmapcolor4f_bufferobject = 0;
8278         rsurface.lightmapcolor4f_bufferoffset = 0;
8279 }
8280
8281 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8282 {
8283         int texturesurfaceindex;
8284         int i;
8285         const float *c;
8286         float *c2;
8287         if (!rsurface.lightmapcolor4f)
8288                 return;
8289         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8290         {
8291                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8292                 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)
8293                 {
8294                         c2[0] = c[0] + r_refdef.scene.ambient;
8295                         c2[1] = c[1] + r_refdef.scene.ambient;
8296                         c2[2] = c[2] + r_refdef.scene.ambient;
8297                         c2[3] = c[3];
8298                 }
8299         }
8300         rsurface.lightmapcolor4f = rsurface.array_color4f;
8301         rsurface.lightmapcolor4f_bufferobject = 0;
8302         rsurface.lightmapcolor4f_bufferoffset = 0;
8303 }
8304
8305 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8306 {
8307         // TODO: optimize
8308         rsurface.lightmapcolor4f = NULL;
8309         rsurface.lightmapcolor4f_bufferobject = 0;
8310         rsurface.lightmapcolor4f_bufferoffset = 0;
8311         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8312         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8313         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8314         GL_Color(r, g, b, a);
8315         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
8316 }
8317
8318 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8319 {
8320         // TODO: optimize applyfog && applycolor case
8321         // just apply fog if necessary, and tint the fog color array if necessary
8322         rsurface.lightmapcolor4f = NULL;
8323         rsurface.lightmapcolor4f_bufferobject = 0;
8324         rsurface.lightmapcolor4f_bufferoffset = 0;
8325         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8326         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8327         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8328         GL_Color(r, g, b, a);
8329         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8330 }
8331
8332 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8333 {
8334         int texturesurfaceindex;
8335         int i;
8336         float *c;
8337         // TODO: optimize
8338         if (texturesurfacelist[0]->lightmapinfo)
8339         {
8340                 // generate color arrays for the surfaces in this list
8341                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8342                 {
8343                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8344                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
8345                         {
8346                                 if (surface->lightmapinfo->samples)
8347                                 {
8348                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
8349                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
8350                                         VectorScale(lm, scale, c);
8351                                         if (surface->lightmapinfo->styles[1] != 255)
8352                                         {
8353                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8354                                                 lm += size3;
8355                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
8356                                                 VectorMA(c, scale, lm, c);
8357                                                 if (surface->lightmapinfo->styles[2] != 255)
8358                                                 {
8359                                                         lm += size3;
8360                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
8361                                                         VectorMA(c, scale, lm, c);
8362                                                         if (surface->lightmapinfo->styles[3] != 255)
8363                                                         {
8364                                                                 lm += size3;
8365                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
8366                                                                 VectorMA(c, scale, lm, c);
8367                                                         }
8368                                                 }
8369                                         }
8370                                 }
8371                                 else
8372                                         VectorClear(c);
8373                                 c[3] = 1;
8374                         }
8375                 }
8376                 rsurface.lightmapcolor4f = rsurface.array_color4f;
8377                 rsurface.lightmapcolor4f_bufferobject = 0;
8378                 rsurface.lightmapcolor4f_bufferoffset = 0;
8379         }
8380         else
8381         {
8382                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8383                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8384                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8385         }
8386         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8387         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8388         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8389         GL_Color(r, g, b, a);
8390         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8391 }
8392
8393 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
8394 {
8395         int texturesurfaceindex;
8396         int i;
8397         float f;
8398         float alpha;
8399         const float *v;
8400         const float *n;
8401         float *c;
8402         vec3_t ambientcolor;
8403         vec3_t diffusecolor;
8404         vec3_t lightdir;
8405         // TODO: optimize
8406         // model lighting
8407         VectorCopy(rsurface.modellight_lightdir, lightdir);
8408         f = 0.5f * r_refdef.lightmapintensity;
8409         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
8410         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
8411         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
8412         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
8413         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
8414         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
8415         alpha = *a;
8416         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
8417         {
8418                 // generate color arrays for the surfaces in this list
8419                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8420                 {
8421                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8422                         int numverts = surface->num_vertices;
8423                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
8424                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
8425                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
8426                         // q3-style directional shading
8427                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
8428                         {
8429                                 if ((f = DotProduct(n, lightdir)) > 0)
8430                                         VectorMA(ambientcolor, f, diffusecolor, c);
8431                                 else
8432                                         VectorCopy(ambientcolor, c);
8433                                 c[3] = alpha;
8434                         }
8435                 }
8436                 *r = 1;
8437                 *g = 1;
8438                 *b = 1;
8439                 *a = 1;
8440                 rsurface.lightmapcolor4f = rsurface.array_color4f;
8441                 rsurface.lightmapcolor4f_bufferobject = 0;
8442                 rsurface.lightmapcolor4f_bufferoffset = 0;
8443                 *applycolor = false;
8444         }
8445         else
8446         {
8447                 *r = ambientcolor[0];
8448                 *g = ambientcolor[1];
8449                 *b = ambientcolor[2];
8450                 rsurface.lightmapcolor4f = NULL;
8451                 rsurface.lightmapcolor4f_bufferobject = 0;
8452                 rsurface.lightmapcolor4f_bufferoffset = 0;
8453         }
8454 }
8455
8456 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8457 {
8458         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
8459         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8460         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8461         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8462         GL_Color(r, g, b, a);
8463         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8464 }
8465
8466 void RSurf_SetupDepthAndCulling(void)
8467 {
8468         // submodels are biased to avoid z-fighting with world surfaces that they
8469         // may be exactly overlapping (avoids z-fighting artifacts on certain
8470         // doors and things in Quake maps)
8471         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
8472         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
8473         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
8474         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
8475 }
8476
8477 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8478 {
8479         // transparent sky would be ridiculous
8480         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8481                 return;
8482         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8483         skyrenderlater = true;
8484         RSurf_SetupDepthAndCulling();
8485         GL_DepthMask(true);
8486         // LordHavoc: HalfLife maps have freaky skypolys so don't use
8487         // skymasking on them, and Quake3 never did sky masking (unlike
8488         // software Quake and software Quake2), so disable the sky masking
8489         // in Quake3 maps as it causes problems with q3map2 sky tricks,
8490         // and skymasking also looks very bad when noclipping outside the
8491         // level, so don't use it then either.
8492         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
8493         {
8494                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
8495                 R_Mesh_ColorPointer(NULL, 0, 0);
8496                 R_Mesh_ResetTextureState();
8497                 if (skyrendermasked)
8498                 {
8499                         R_SetupShader_DepthOrShadow();
8500                         // depth-only (masking)
8501                         GL_ColorMask(0,0,0,0);
8502                         // just to make sure that braindead drivers don't draw
8503                         // anything despite that colormask...
8504                         GL_BlendFunc(GL_ZERO, GL_ONE);
8505                 }
8506                 else
8507                 {
8508                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8509                         // fog sky
8510                         GL_BlendFunc(GL_ONE, GL_ZERO);
8511                 }
8512                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8513                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8514                 if (skyrendermasked)
8515                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8516         }
8517         R_Mesh_ResetTextureState();
8518         GL_Color(1, 1, 1, 1);
8519 }
8520
8521 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
8522 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
8523 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8524 {
8525         qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
8526         qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
8527
8528         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
8529                 return;
8530
8531         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
8532                 R_Mesh_ColorPointer(NULL, 0, 0);
8533         else
8534                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
8535
8536         if (refract)
8537         {
8538                 // render background
8539                 GL_BlendFunc(GL_ONE, GL_ZERO);
8540                 GL_DepthMask(true);
8541                 GL_AlphaTest(false);
8542
8543                 GL_Color(1, 1, 1, 1);
8544                 R_Mesh_ColorPointer(NULL, 0, 0);
8545
8546                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
8547                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
8548                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8549                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
8550                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
8551                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
8552                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8553                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8554                 GL_LockArrays(0, 0);
8555
8556                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
8557                 GL_DepthMask(false);
8558                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
8559                         R_Mesh_ColorPointer(NULL, 0, 0);
8560                 else
8561                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
8562         }
8563
8564         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
8565
8566         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
8567         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8568         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
8569         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
8570         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
8571         if (!prepass)
8572                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8573
8574         if (refract)
8575         {
8576                 GL_BlendFunc(GL_ONE, GL_ZERO);
8577                 GL_DepthMask(true);
8578                 GL_AlphaTest(false);
8579         }
8580         else
8581         {
8582                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
8583                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8584                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
8585         }
8586
8587         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8588         {
8589                 if (refract || reflect)
8590                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8591                 else
8592                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
8593         }
8594         else
8595         {
8596                 if (refract || reflect)
8597                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8598                 else
8599                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8600         }
8601         GL_LockArrays(0, 0);
8602 }
8603
8604 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8605 {
8606         // OpenGL 1.3 path - anything not completely ancient
8607         int texturesurfaceindex;
8608         qboolean applycolor;
8609         qboolean applyfog;
8610         int layerindex;
8611         const texturelayer_t *layer;
8612         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8613
8614         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
8615         {
8616                 vec4_t layercolor;
8617                 int layertexrgbscale;
8618                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8619                 {
8620                         if (layerindex == 0)
8621                                 GL_AlphaTest(true);
8622                         else
8623                         {
8624                                 GL_AlphaTest(false);
8625                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
8626                         }
8627                 }
8628                 GL_DepthMask(layer->depthmask && writedepth);
8629                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
8630                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
8631                 {
8632                         layertexrgbscale = 4;
8633                         VectorScale(layer->color, 0.25f, layercolor);
8634                 }
8635                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
8636                 {
8637                         layertexrgbscale = 2;
8638                         VectorScale(layer->color, 0.5f, layercolor);
8639                 }
8640                 else
8641                 {
8642                         layertexrgbscale = 1;
8643                         VectorScale(layer->color, 1.0f, layercolor);
8644                 }
8645                 layercolor[3] = layer->color[3];
8646                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
8647                 R_Mesh_ColorPointer(NULL, 0, 0);
8648                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
8649                 switch (layer->type)
8650                 {
8651                 case TEXTURELAYERTYPE_LITTEXTURE:
8652                         // single-pass lightmapped texture with 2x rgbscale
8653                         //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8654                         R_Mesh_TexMatrix(0, NULL);
8655                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8656                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8657                         R_Mesh_TexBind(1, R_GetTexture(layer->texture));
8658                         R_Mesh_TexMatrix(1, &layer->texmatrix);
8659                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8660                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8661                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8662                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8663                         else if (rsurface.uselightmaptexture)
8664                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8665                         else
8666                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8667                         break;
8668                 case TEXTURELAYERTYPE_TEXTURE:
8669                         // singletexture unlit texture with transparency support
8670                         R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8671                         R_Mesh_TexMatrix(0, &layer->texmatrix);
8672                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8673                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8674                         R_Mesh_TexBind(1, 0);
8675                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
8676                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8677                         break;
8678                 case TEXTURELAYERTYPE_FOG:
8679                         // singletexture fogging
8680                         if (layer->texture)
8681                         {
8682                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8683                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8684                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8685                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8686                         }
8687                         else
8688                         {
8689                                 R_Mesh_TexBind(0, 0);
8690                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8691                         }
8692                         R_Mesh_TexBind(1, 0);
8693                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
8694                         // generate a color array for the fog pass
8695                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8696                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8697                         {
8698                                 int i;
8699                                 float f;
8700                                 const float *v;
8701                                 float *c;
8702                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8703                                 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)
8704                                 {
8705                                         f = 1 - RSurf_FogVertex(v);
8706                                         c[0] = layercolor[0];
8707                                         c[1] = layercolor[1];
8708                                         c[2] = layercolor[2];
8709                                         c[3] = f * layercolor[3];
8710                                 }
8711                         }
8712                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8713                         break;
8714                 default:
8715                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8716                 }
8717                 GL_LockArrays(0, 0);
8718         }
8719         CHECKGLERROR
8720         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8721         {
8722                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8723                 GL_AlphaTest(false);
8724         }
8725 }
8726
8727 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8728 {
8729         // OpenGL 1.1 - crusty old voodoo path
8730         int texturesurfaceindex;
8731         qboolean applyfog;
8732         int layerindex;
8733         const texturelayer_t *layer;
8734         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8735
8736         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
8737         {
8738                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8739                 {
8740                         if (layerindex == 0)
8741                                 GL_AlphaTest(true);
8742                         else
8743                         {
8744                                 GL_AlphaTest(false);
8745                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
8746                         }
8747                 }
8748                 GL_DepthMask(layer->depthmask && writedepth);
8749                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
8750                 R_Mesh_ColorPointer(NULL, 0, 0);
8751                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
8752                 switch (layer->type)
8753                 {
8754                 case TEXTURELAYERTYPE_LITTEXTURE:
8755                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
8756                         {
8757                                 // two-pass lit texture with 2x rgbscale
8758                                 // first the lightmap pass
8759                                 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8760                                 R_Mesh_TexMatrix(0, NULL);
8761                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8762                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8763                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8764                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8765                                 else if (rsurface.uselightmaptexture)
8766                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8767                                 else
8768                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8769                                 GL_LockArrays(0, 0);
8770                                 // then apply the texture to it
8771                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8772                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8773                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8774                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8775                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8776                                 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);
8777                         }
8778                         else
8779                         {
8780                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
8781                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8782                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8783                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8784                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8785                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8786                                         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);
8787                                 else
8788                                         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);
8789                         }
8790                         break;
8791                 case TEXTURELAYERTYPE_TEXTURE:
8792                         // singletexture unlit texture with transparency support
8793                         R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8794                         R_Mesh_TexMatrix(0, &layer->texmatrix);
8795                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8796                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8797                         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);
8798                         break;
8799                 case TEXTURELAYERTYPE_FOG:
8800                         // singletexture fogging
8801                         if (layer->texture)
8802                         {
8803                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8804                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8805                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8806                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8807                         }
8808                         else
8809                         {
8810                                 R_Mesh_TexBind(0, 0);
8811                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8812                         }
8813                         // generate a color array for the fog pass
8814                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8815                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8816                         {
8817                                 int i;
8818                                 float f;
8819                                 const float *v;
8820                                 float *c;
8821                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8822                                 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)
8823                                 {
8824                                         f = 1 - RSurf_FogVertex(v);
8825                                         c[0] = layer->color[0];
8826                                         c[1] = layer->color[1];
8827                                         c[2] = layer->color[2];
8828                                         c[3] = f * layer->color[3];
8829                                 }
8830                         }
8831                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8832                         break;
8833                 default:
8834                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8835                 }
8836                 GL_LockArrays(0, 0);
8837         }
8838         CHECKGLERROR
8839         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8840         {
8841                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8842                 GL_AlphaTest(false);
8843         }
8844 }
8845
8846 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8847 {
8848         float c[4];
8849
8850         GL_AlphaTest(false);
8851         R_Mesh_ColorPointer(NULL, 0, 0);
8852         R_Mesh_ResetTextureState();
8853         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8854
8855         if(rsurface.texture && rsurface.texture->currentskinframe)
8856         {
8857                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8858                 c[3] *= rsurface.texture->currentalpha;
8859         }
8860         else
8861         {
8862                 c[0] = 1;
8863                 c[1] = 0;
8864                 c[2] = 1;
8865                 c[3] = 1;
8866         }
8867
8868         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
8869         {
8870                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8871                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8872                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8873         }
8874
8875         // brighten it up (as texture value 127 means "unlit")
8876         c[0] *= 2 * r_refdef.view.colorscale;
8877         c[1] *= 2 * r_refdef.view.colorscale;
8878         c[2] *= 2 * r_refdef.view.colorscale;
8879
8880         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8881                 c[3] *= r_wateralpha.value;
8882
8883         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8884         {
8885                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8886                 GL_DepthMask(false);
8887         }
8888         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8889         {
8890                 GL_BlendFunc(GL_ONE, GL_ONE);
8891                 GL_DepthMask(false);
8892         }
8893         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8894         {
8895                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8896                 GL_DepthMask(false);
8897         }
8898         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8899         {
8900                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8901                 GL_DepthMask(false);
8902         }
8903         else
8904         {
8905                 GL_BlendFunc(GL_ONE, GL_ZERO);
8906                 GL_DepthMask(writedepth);
8907         }
8908
8909         rsurface.lightmapcolor4f = NULL;
8910
8911         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8912         {
8913                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8914
8915                 rsurface.lightmapcolor4f = NULL;
8916                 rsurface.lightmapcolor4f_bufferobject = 0;
8917                 rsurface.lightmapcolor4f_bufferoffset = 0;
8918         }
8919         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8920         {
8921                 qboolean applycolor = true;
8922                 float one = 1.0;
8923
8924                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8925
8926                 r_refdef.lightmapintensity = 1;
8927                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8928                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8929         }
8930         else
8931         {
8932                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8933
8934                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8935                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8936                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8937         }
8938
8939         if(!rsurface.lightmapcolor4f)
8940                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8941
8942         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8943         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8944         if(r_refdef.fogenabled)
8945                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8946
8947         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8948         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8949 }
8950
8951 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8952 {
8953         CHECKGLERROR
8954         RSurf_SetupDepthAndCulling();
8955         if (r_showsurfaces.integer == 3 && !prepass)
8956         {
8957                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8958                 return;
8959         }
8960         switch (vid.renderpath)
8961         {
8962         case RENDERPATH_GL20:
8963         case RENDERPATH_CGGL:
8964                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8965                 break;
8966         case RENDERPATH_GL13:
8967                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8968                 break;
8969         case RENDERPATH_GL11:
8970                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8971                 break;
8972         }
8973         CHECKGLERROR
8974 }
8975
8976 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8977 {
8978         CHECKGLERROR
8979         RSurf_SetupDepthAndCulling();
8980         if (r_showsurfaces.integer == 3 && !prepass)
8981         {
8982                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8983                 return;
8984         }
8985         switch (vid.renderpath)
8986         {
8987         case RENDERPATH_GL20:
8988         case RENDERPATH_CGGL:
8989                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8990                 break;
8991         case RENDERPATH_GL13:
8992                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8993                 break;
8994         case RENDERPATH_GL11:
8995                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8996                 break;
8997         }
8998         CHECKGLERROR
8999 }
9000
9001 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9002 {
9003         int i, j;
9004         int texturenumsurfaces, endsurface;
9005         texture_t *texture;
9006         const msurface_t *surface;
9007         const msurface_t *texturesurfacelist[256];
9008
9009         // if the model is static it doesn't matter what value we give for
9010         // wantnormals and wanttangents, so this logic uses only rules applicable
9011         // to a model, knowing that they are meaningless otherwise
9012         if (ent == r_refdef.scene.worldentity)
9013                 RSurf_ActiveWorldEntity();
9014         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9015                 RSurf_ActiveModelEntity(ent, false, false, false);
9016         else
9017         {
9018                 switch (vid.renderpath)
9019                 {
9020                 case RENDERPATH_GL20:
9021                 case RENDERPATH_CGGL:
9022                         RSurf_ActiveModelEntity(ent, true, true, false);
9023                         break;
9024                 case RENDERPATH_GL13:
9025                 case RENDERPATH_GL11:
9026                         RSurf_ActiveModelEntity(ent, true, false, false);
9027                         break;
9028                 }
9029         }
9030
9031         if (r_transparentdepthmasking.integer)
9032         {
9033                 qboolean setup = false;
9034                 for (i = 0;i < numsurfaces;i = j)
9035                 {
9036                         j = i + 1;
9037                         surface = rsurface.modelsurfaces + surfacelist[i];
9038                         texture = surface->texture;
9039                         rsurface.texture = R_GetCurrentTexture(texture);
9040                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9041                         // scan ahead until we find a different texture
9042                         endsurface = min(i + 1024, numsurfaces);
9043                         texturenumsurfaces = 0;
9044                         texturesurfacelist[texturenumsurfaces++] = surface;
9045                         for (;j < endsurface;j++)
9046                         {
9047                                 surface = rsurface.modelsurfaces + surfacelist[j];
9048                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
9049                                         break;
9050                                 texturesurfacelist[texturenumsurfaces++] = surface;
9051                         }
9052                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9053                                 continue;
9054                         // render the range of surfaces as depth
9055                         if (!setup)
9056                         {
9057                                 setup = true;
9058                                 GL_ColorMask(0,0,0,0);
9059                                 GL_Color(1,1,1,1);
9060                                 GL_DepthTest(true);
9061                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9062                                 GL_DepthMask(true);
9063                                 GL_AlphaTest(false);
9064                                 R_Mesh_ColorPointer(NULL, 0, 0);
9065                                 R_Mesh_ResetTextureState();
9066                                 R_SetupShader_DepthOrShadow();
9067                         }
9068                         RSurf_SetupDepthAndCulling();
9069                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9070                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9071                 }
9072                 if (setup)
9073                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9074         }
9075
9076         for (i = 0;i < numsurfaces;i = j)
9077         {
9078                 j = i + 1;
9079                 surface = rsurface.modelsurfaces + surfacelist[i];
9080                 texture = surface->texture;
9081                 rsurface.texture = R_GetCurrentTexture(texture);
9082                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9083                 // scan ahead until we find a different texture
9084                 endsurface = min(i + 1024, numsurfaces);
9085                 texturenumsurfaces = 0;
9086                 texturesurfacelist[texturenumsurfaces++] = surface;
9087                 for (;j < endsurface;j++)
9088                 {
9089                         surface = rsurface.modelsurfaces + surfacelist[j];
9090                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
9091                                 break;
9092                         texturesurfacelist[texturenumsurfaces++] = surface;
9093                 }
9094                 // render the range of surfaces
9095                 if (ent == r_refdef.scene.worldentity)
9096                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9097                 else
9098                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9099         }
9100         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9101         GL_AlphaTest(false);
9102 }
9103
9104 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9105 {
9106         // transparent surfaces get pushed off into the transparent queue
9107         int surfacelistindex;
9108         const msurface_t *surface;
9109         vec3_t tempcenter, center;
9110         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9111         {
9112                 surface = texturesurfacelist[surfacelistindex];
9113                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9114                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9115                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9116                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9117                 if (queueentity->transparent_offset) // transparent offset
9118                 {
9119                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9120                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9121                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9122                 }
9123                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9124         }
9125 }
9126
9127 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9128 {
9129         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9130         CHECKGLERROR
9131         if (depthonly)
9132         {
9133                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9134                         return;
9135                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9136                         return;
9137                 RSurf_SetupDepthAndCulling();
9138                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9139                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9140         }
9141         else if (prepass)
9142         {
9143                 if (!rsurface.texture->currentnumlayers)
9144                         return;
9145                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9146                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9147                 else
9148                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9149         }
9150         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
9151         {
9152                 RSurf_SetupDepthAndCulling();
9153                 GL_AlphaTest(false);
9154                 R_Mesh_ColorPointer(NULL, 0, 0);
9155                 R_Mesh_ResetTextureState();
9156                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9157                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9158                 GL_DepthMask(true);
9159                 GL_BlendFunc(GL_ONE, GL_ZERO);
9160                 GL_Color(0, 0, 0, 1);
9161                 GL_DepthTest(writedepth);
9162                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9163         }
9164         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
9165         {
9166                 RSurf_SetupDepthAndCulling();
9167                 GL_AlphaTest(false);
9168                 R_Mesh_ColorPointer(NULL, 0, 0);
9169                 R_Mesh_ResetTextureState();
9170                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9171                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9172                 GL_DepthMask(true);
9173                 GL_BlendFunc(GL_ONE, GL_ZERO);
9174                 GL_DepthTest(true);
9175                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
9176         }
9177         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
9178                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9179         else if (!rsurface.texture->currentnumlayers)
9180                 return;
9181         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9182         {
9183                 // in the deferred case, transparent surfaces were queued during prepass
9184                 if (!r_shadow_usingdeferredprepass)
9185                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9186         }
9187         else
9188         {
9189                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9190                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9191         }
9192         CHECKGLERROR
9193 }
9194
9195 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9196 {
9197         int i, j;
9198         texture_t *texture;
9199         // break the surface list down into batches by texture and use of lightmapping
9200         for (i = 0;i < numsurfaces;i = j)
9201         {
9202                 j = i + 1;
9203                 // texture is the base texture pointer, rsurface.texture is the
9204                 // current frame/skin the texture is directing us to use (for example
9205                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9206                 // use skin 1 instead)
9207                 texture = surfacelist[i]->texture;
9208                 rsurface.texture = R_GetCurrentTexture(texture);
9209                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
9210                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9211                 {
9212                         // if this texture is not the kind we want, skip ahead to the next one
9213                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9214                                 ;
9215                         continue;
9216                 }
9217                 // simply scan ahead until we find a different texture or lightmap state
9218                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
9219                         ;
9220                 // render the range of surfaces
9221                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
9222         }
9223 }
9224
9225 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
9226 {
9227         CHECKGLERROR
9228         if (depthonly)
9229         {
9230                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9231                         return;
9232                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9233                         return;
9234                 RSurf_SetupDepthAndCulling();
9235                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9236                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9237         }
9238         else if (prepass)
9239         {
9240                 if (!rsurface.texture->currentnumlayers)
9241                         return;
9242                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9243                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9244                 else
9245                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9246         }
9247         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
9248         {
9249                 RSurf_SetupDepthAndCulling();
9250                 GL_AlphaTest(false);
9251                 R_Mesh_ColorPointer(NULL, 0, 0);
9252                 R_Mesh_ResetTextureState();
9253                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9254                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9255                 GL_DepthMask(true);
9256                 GL_BlendFunc(GL_ONE, GL_ZERO);
9257                 GL_Color(0, 0, 0, 1);
9258                 GL_DepthTest(writedepth);
9259                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9260         }
9261         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9262         {
9263                 RSurf_SetupDepthAndCulling();
9264                 GL_AlphaTest(false);
9265                 R_Mesh_ColorPointer(NULL, 0, 0);
9266                 R_Mesh_ResetTextureState();
9267                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9268                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9269                 GL_DepthMask(true);
9270                 GL_BlendFunc(GL_ONE, GL_ZERO);
9271                 GL_DepthTest(true);
9272                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
9273         }
9274         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
9275                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9276         else if (!rsurface.texture->currentnumlayers)
9277                 return;
9278         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9279         {
9280                 // in the deferred case, transparent surfaces were queued during prepass
9281                 if (!r_shadow_usingdeferredprepass)
9282                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9283         }
9284         else
9285         {
9286                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9287                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9288         }
9289         CHECKGLERROR
9290 }
9291
9292 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9293 {
9294         int i, j;
9295         texture_t *texture;
9296         // break the surface list down into batches by texture and use of lightmapping
9297         for (i = 0;i < numsurfaces;i = j)
9298         {
9299                 j = i + 1;
9300                 // texture is the base texture pointer, rsurface.texture is the
9301                 // current frame/skin the texture is directing us to use (for example
9302                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9303                 // use skin 1 instead)
9304                 texture = surfacelist[i]->texture;
9305                 rsurface.texture = R_GetCurrentTexture(texture);
9306                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
9307                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9308                 {
9309                         // if this texture is not the kind we want, skip ahead to the next one
9310                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9311                                 ;
9312                         continue;
9313                 }
9314                 // simply scan ahead until we find a different texture or lightmap state
9315                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
9316                         ;
9317                 // render the range of surfaces
9318                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
9319         }
9320 }
9321
9322 float locboxvertex3f[6*4*3] =
9323 {
9324         1,0,1, 1,0,0, 1,1,0, 1,1,1,
9325         0,1,1, 0,1,0, 0,0,0, 0,0,1,
9326         1,1,1, 1,1,0, 0,1,0, 0,1,1,
9327         0,0,1, 0,0,0, 1,0,0, 1,0,1,
9328         0,0,1, 1,0,1, 1,1,1, 0,1,1,
9329         1,0,0, 0,0,0, 0,1,0, 1,1,0
9330 };
9331
9332 unsigned short locboxelements[6*2*3] =
9333 {
9334          0, 1, 2, 0, 2, 3,
9335          4, 5, 6, 4, 6, 7,
9336          8, 9,10, 8,10,11,
9337         12,13,14, 12,14,15,
9338         16,17,18, 16,18,19,
9339         20,21,22, 20,22,23
9340 };
9341
9342 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9343 {
9344         int i, j;
9345         cl_locnode_t *loc = (cl_locnode_t *)ent;
9346         vec3_t mins, size;
9347         float vertex3f[6*4*3];
9348         CHECKGLERROR
9349         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9350         GL_DepthMask(false);
9351         GL_DepthRange(0, 1);
9352         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9353         GL_DepthTest(true);
9354         GL_CullFace(GL_NONE);
9355         R_EntityMatrix(&identitymatrix);
9356
9357         R_Mesh_VertexPointer(vertex3f, 0, 0);
9358         R_Mesh_ColorPointer(NULL, 0, 0);
9359         R_Mesh_ResetTextureState();
9360         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9361
9362         i = surfacelist[0];
9363         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9364                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9365                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9366                         surfacelist[0] < 0 ? 0.5f : 0.125f);
9367
9368         if (VectorCompare(loc->mins, loc->maxs))
9369         {
9370                 VectorSet(size, 2, 2, 2);
9371                 VectorMA(loc->mins, -0.5f, size, mins);
9372         }
9373         else
9374         {
9375                 VectorCopy(loc->mins, mins);
9376                 VectorSubtract(loc->maxs, loc->mins, size);
9377         }
9378
9379         for (i = 0;i < 6*4*3;)
9380                 for (j = 0;j < 3;j++, i++)
9381                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
9382
9383         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
9384 }
9385
9386 void R_DrawLocs(void)
9387 {
9388         int index;
9389         cl_locnode_t *loc, *nearestloc;
9390         vec3_t center;
9391         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
9392         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
9393         {
9394                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
9395                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
9396         }
9397 }
9398
9399 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
9400 {
9401         if (decalsystem->decals)
9402                 Mem_Free(decalsystem->decals);
9403         memset(decalsystem, 0, sizeof(*decalsystem));
9404 }
9405
9406 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)
9407 {
9408         tridecal_t *decal;
9409         tridecal_t *decals;
9410         int i;
9411         int maxdecals;
9412
9413         // expand or initialize the system
9414         if (decalsystem->maxdecals <= decalsystem->numdecals)
9415         {
9416                 decalsystem_t old = *decalsystem;
9417                 qboolean useshortelements;
9418                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
9419                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
9420                 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)));
9421                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
9422                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
9423                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
9424                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
9425                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
9426                 if (decalsystem->numdecals)
9427                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
9428                 if (old.decals)
9429                         Mem_Free(old.decals);
9430                 for (i = 0;i < decalsystem->maxdecals*3;i++)
9431                         decalsystem->element3i[i] = i;
9432                 if (useshortelements)
9433                         for (i = 0;i < decalsystem->maxdecals*3;i++)
9434                                 decalsystem->element3s[i] = i;
9435         }
9436
9437         // grab a decal and search for another free slot for the next one
9438         maxdecals = decalsystem->maxdecals;
9439         decals = decalsystem->decals;
9440         decal = decalsystem->decals + (i = decalsystem->freedecal++);
9441         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
9442                 ;
9443         decalsystem->freedecal = i;
9444         if (decalsystem->numdecals <= i)
9445                 decalsystem->numdecals = i + 1;
9446
9447         // initialize the decal
9448         decal->lived = 0;
9449         decal->triangleindex = triangleindex;
9450         decal->surfaceindex = surfaceindex;
9451         decal->decalsequence = decalsequence;
9452         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
9453         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
9454         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
9455         decal->color4ub[0][3] = 255;
9456         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
9457         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
9458         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
9459         decal->color4ub[1][3] = 255;
9460         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
9461         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
9462         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
9463         decal->color4ub[2][3] = 255;
9464         decal->vertex3f[0][0] = v0[0];
9465         decal->vertex3f[0][1] = v0[1];
9466         decal->vertex3f[0][2] = v0[2];
9467         decal->vertex3f[1][0] = v1[0];
9468         decal->vertex3f[1][1] = v1[1];
9469         decal->vertex3f[1][2] = v1[2];
9470         decal->vertex3f[2][0] = v2[0];
9471         decal->vertex3f[2][1] = v2[1];
9472         decal->vertex3f[2][2] = v2[2];
9473         decal->texcoord2f[0][0] = t0[0];
9474         decal->texcoord2f[0][1] = t0[1];
9475         decal->texcoord2f[1][0] = t1[0];
9476         decal->texcoord2f[1][1] = t1[1];
9477         decal->texcoord2f[2][0] = t2[0];
9478         decal->texcoord2f[2][1] = t2[1];
9479 }
9480
9481 extern cvar_t cl_decals_bias;
9482 extern cvar_t cl_decals_models;
9483 extern cvar_t cl_decals_newsystem_intensitymultiplier;
9484 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)
9485 {
9486         matrix4x4_t projection;
9487         decalsystem_t *decalsystem;
9488         qboolean dynamic;
9489         dp_model_t *model;
9490         const float *vertex3f;
9491         const msurface_t *surface;
9492         const msurface_t *surfaces;
9493         const int *surfacelist;
9494         const texture_t *texture;
9495         int numvertices;
9496         int numtriangles;
9497         int numsurfacelist;
9498         int surfacelistindex;
9499         int surfaceindex;
9500         int triangleindex;
9501         int decalsurfaceindex;
9502         int cornerindex;
9503         int index;
9504         int numpoints;
9505         const int *e;
9506         float localorigin[3];
9507         float localnormal[3];
9508         float localmins[3];
9509         float localmaxs[3];
9510         float localsize;
9511         float ilocalsize;
9512         float v[9][3];
9513         float tc[9][2];
9514         float c[9][4];
9515         //float normal[3];
9516         float planes[6][4];
9517         float f;
9518         float points[2][9][3];
9519         float angles[3];
9520         float temp[3];
9521
9522         decalsystem = &ent->decalsystem;
9523         model = ent->model;
9524         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
9525         {
9526                 R_DecalSystem_Reset(&ent->decalsystem);
9527                 return;
9528         }
9529
9530         if (!model->brush.data_nodes && !cl_decals_models.integer)
9531         {
9532                 if (decalsystem->model)
9533                         R_DecalSystem_Reset(decalsystem);
9534                 return;
9535         }
9536
9537         if (decalsystem->model != model)
9538                 R_DecalSystem_Reset(decalsystem);
9539         decalsystem->model = model;
9540
9541         RSurf_ActiveModelEntity(ent, false, false, false);
9542
9543         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
9544         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
9545         VectorNormalize(localnormal);
9546         localsize = worldsize*rsurface.inversematrixscale;
9547         ilocalsize = 1.0f / localsize;
9548         localmins[0] = localorigin[0] - localsize;
9549         localmins[1] = localorigin[1] - localsize;
9550         localmins[2] = localorigin[2] - localsize;
9551         localmaxs[0] = localorigin[0] + localsize;
9552         localmaxs[1] = localorigin[1] + localsize;
9553         localmaxs[2] = localorigin[2] + localsize;
9554
9555         //VectorCopy(localnormal, planes[4]);
9556         //VectorVectors(planes[4], planes[2], planes[0]);
9557         AnglesFromVectors(angles, localnormal, NULL, false);
9558         AngleVectors(angles, planes[0], planes[2], planes[4]);
9559         VectorNegate(planes[0], planes[1]);
9560         VectorNegate(planes[2], planes[3]);
9561         VectorNegate(planes[4], planes[5]);
9562         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
9563         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
9564         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
9565         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
9566         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
9567         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
9568
9569 #if 1
9570 // works
9571 {
9572         matrix4x4_t forwardprojection;
9573         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
9574         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
9575 }
9576 #else
9577 // broken
9578 {
9579         float projectionvector[4][3];
9580         VectorScale(planes[0], ilocalsize, projectionvector[0]);
9581         VectorScale(planes[2], ilocalsize, projectionvector[1]);
9582         VectorScale(planes[4], ilocalsize, projectionvector[2]);
9583         projectionvector[0][0] = planes[0][0] * ilocalsize;
9584         projectionvector[0][1] = planes[1][0] * ilocalsize;
9585         projectionvector[0][2] = planes[2][0] * ilocalsize;
9586         projectionvector[1][0] = planes[0][1] * ilocalsize;
9587         projectionvector[1][1] = planes[1][1] * ilocalsize;
9588         projectionvector[1][2] = planes[2][1] * ilocalsize;
9589         projectionvector[2][0] = planes[0][2] * ilocalsize;
9590         projectionvector[2][1] = planes[1][2] * ilocalsize;
9591         projectionvector[2][2] = planes[2][2] * ilocalsize;
9592         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
9593         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
9594         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
9595         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
9596 }
9597 #endif
9598
9599         dynamic = model->surfmesh.isanimated;
9600         vertex3f = rsurface.modelvertex3f;
9601         numsurfacelist = model->nummodelsurfaces;
9602         surfacelist = model->sortedmodelsurfaces;
9603         surfaces = model->data_surfaces;
9604         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
9605         {
9606                 surfaceindex = surfacelist[surfacelistindex];
9607                 surface = surfaces + surfaceindex;
9608                 // skip transparent surfaces
9609                 texture = surface->texture;
9610                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9611                         continue;
9612                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
9613                         continue;
9614                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
9615                         continue;
9616                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
9617                 numvertices = surface->num_vertices;
9618                 numtriangles = surface->num_triangles;
9619                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
9620                 {
9621                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
9622                         {
9623                                 index = 3*e[cornerindex];
9624                                 VectorCopy(vertex3f + index, v[cornerindex]);
9625                         }
9626                         // cull backfaces
9627                         //TriangleNormal(v[0], v[1], v[2], normal);
9628                         //if (DotProduct(normal, localnormal) < 0.0f)
9629                         //      continue;
9630                         // clip by each of the box planes formed from the projection matrix
9631                         // if anything survives, we emit the decal
9632                         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]);
9633                         if (numpoints < 3)
9634                                 continue;
9635                         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]);
9636                         if (numpoints < 3)
9637                                 continue;
9638                         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]);
9639                         if (numpoints < 3)
9640                                 continue;
9641                         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]);
9642                         if (numpoints < 3)
9643                                 continue;
9644                         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]);
9645                         if (numpoints < 3)
9646                                 continue;
9647                         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]);
9648                         if (numpoints < 3)
9649                                 continue;
9650                         // some part of the triangle survived, so we have to accept it...
9651                         if (dynamic)
9652                         {
9653                                 // dynamic always uses the original triangle
9654                                 numpoints = 3;
9655                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9656                                 {
9657                                         index = 3*e[cornerindex];
9658                                         VectorCopy(vertex3f + index, v[cornerindex]);
9659                                 }
9660                         }
9661                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
9662                         {
9663                                 // convert vertex positions to texcoords
9664                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
9665                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
9666                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
9667                                 // calculate distance fade from the projection origin
9668                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
9669                                 f = bound(0.0f, f, 1.0f);
9670                                 c[cornerindex][0] = r * f;
9671                                 c[cornerindex][1] = g * f;
9672                                 c[cornerindex][2] = b * f;
9673                                 c[cornerindex][3] = 1.0f;
9674                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
9675                         }
9676                         if (dynamic)
9677                                 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);
9678                         else
9679                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
9680                                         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);
9681                 }
9682         }
9683 }
9684
9685 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
9686 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)
9687 {
9688         int renderentityindex;
9689         float worldmins[3];
9690         float worldmaxs[3];
9691         entity_render_t *ent;
9692
9693         if (!cl_decals_newsystem.integer)
9694                 return;
9695
9696         worldmins[0] = worldorigin[0] - worldsize;
9697         worldmins[1] = worldorigin[1] - worldsize;
9698         worldmins[2] = worldorigin[2] - worldsize;
9699         worldmaxs[0] = worldorigin[0] + worldsize;
9700         worldmaxs[1] = worldorigin[1] + worldsize;
9701         worldmaxs[2] = worldorigin[2] + worldsize;
9702
9703         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9704
9705         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
9706         {
9707                 ent = r_refdef.scene.entities[renderentityindex];
9708                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
9709                         continue;
9710
9711                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9712         }
9713 }
9714
9715 typedef struct r_decalsystem_splatqueue_s
9716 {
9717         vec3_t worldorigin;
9718         vec3_t worldnormal;
9719         float color[4];
9720         float tcrange[4];
9721         float worldsize;
9722         int decalsequence;
9723 }
9724 r_decalsystem_splatqueue_t;
9725
9726 int r_decalsystem_numqueued = 0;
9727 #define MAX_DECALSYSTEM_QUEUE 1024
9728 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
9729
9730 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)
9731 {
9732         r_decalsystem_splatqueue_t *queue;
9733
9734         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
9735                 return;
9736
9737         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
9738         VectorCopy(worldorigin, queue->worldorigin);
9739         VectorCopy(worldnormal, queue->worldnormal);
9740         Vector4Set(queue->color, r, g, b, a);
9741         Vector4Set(queue->tcrange, s1, t1, s2, t2);
9742         queue->worldsize = worldsize;
9743         queue->decalsequence = cl.decalsequence++;
9744 }
9745
9746 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
9747 {
9748         int i;
9749         r_decalsystem_splatqueue_t *queue;
9750
9751         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
9752                 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);
9753         r_decalsystem_numqueued = 0;
9754 }
9755
9756 extern cvar_t cl_decals_max;
9757 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
9758 {
9759         int i;
9760         decalsystem_t *decalsystem = &ent->decalsystem;
9761         int numdecals;
9762         int killsequence;
9763         tridecal_t *decal;
9764         float frametime;
9765         float lifetime;
9766
9767         if (!decalsystem->numdecals)
9768                 return;
9769
9770         if (r_showsurfaces.integer)
9771                 return;
9772
9773         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9774         {
9775                 R_DecalSystem_Reset(decalsystem);
9776                 return;
9777         }
9778
9779         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
9780         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
9781
9782         if (decalsystem->lastupdatetime)
9783                 frametime = (cl.time - decalsystem->lastupdatetime);
9784         else
9785                 frametime = 0;
9786         decalsystem->lastupdatetime = cl.time;
9787         decal = decalsystem->decals;
9788         numdecals = decalsystem->numdecals;
9789
9790         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9791         {
9792                 if (decal->color4ub[0][3])
9793                 {
9794                         decal->lived += frametime;
9795                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
9796                         {
9797                                 memset(decal, 0, sizeof(*decal));
9798                                 if (decalsystem->freedecal > i)
9799                                         decalsystem->freedecal = i;
9800                         }
9801                 }
9802         }
9803         decal = decalsystem->decals;
9804         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
9805                 numdecals--;
9806
9807         // collapse the array by shuffling the tail decals into the gaps
9808         for (;;)
9809         {
9810                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
9811                         decalsystem->freedecal++;
9812                 if (decalsystem->freedecal == numdecals)
9813                         break;
9814                 decal[decalsystem->freedecal] = decal[--numdecals];
9815         }
9816
9817         decalsystem->numdecals = numdecals;
9818
9819         if (numdecals <= 0)
9820         {
9821                 // if there are no decals left, reset decalsystem
9822                 R_DecalSystem_Reset(decalsystem);
9823         }
9824 }
9825
9826 extern skinframe_t *decalskinframe;
9827 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9828 {
9829         int i;
9830         decalsystem_t *decalsystem = &ent->decalsystem;
9831         int numdecals;
9832         tridecal_t *decal;
9833         float fadedelay;
9834         float faderate;
9835         float alpha;
9836         float *v3f;
9837         float *c4f;
9838         float *t2f;
9839         const int *e;
9840         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9841         int numtris = 0;
9842
9843         numdecals = decalsystem->numdecals;
9844         if (!numdecals)
9845                 return;
9846
9847         if (r_showsurfaces.integer)
9848                 return;
9849
9850         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9851         {
9852                 R_DecalSystem_Reset(decalsystem);
9853                 return;
9854         }
9855
9856         // if the model is static it doesn't matter what value we give for
9857         // wantnormals and wanttangents, so this logic uses only rules applicable
9858         // to a model, knowing that they are meaningless otherwise
9859         if (ent == r_refdef.scene.worldentity)
9860                 RSurf_ActiveWorldEntity();
9861         else
9862                 RSurf_ActiveModelEntity(ent, false, false, false);
9863
9864         decalsystem->lastupdatetime = cl.time;
9865         decal = decalsystem->decals;
9866
9867         fadedelay = cl_decals_time.value;
9868         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9869
9870         // update vertex positions for animated models
9871         v3f = decalsystem->vertex3f;
9872         c4f = decalsystem->color4f;
9873         t2f = decalsystem->texcoord2f;
9874         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9875         {
9876                 if (!decal->color4ub[0][3])
9877                         continue;
9878
9879                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9880                         continue;
9881
9882                 // update color values for fading decals
9883                 if (decal->lived >= cl_decals_time.value)
9884                 {
9885                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9886                         alpha *= (1.0f/255.0f);
9887                 }
9888                 else
9889                         alpha = 1.0f/255.0f;
9890
9891                 c4f[ 0] = decal->color4ub[0][0] * alpha;
9892                 c4f[ 1] = decal->color4ub[0][1] * alpha;
9893                 c4f[ 2] = decal->color4ub[0][2] * alpha;
9894                 c4f[ 3] = 1;
9895                 c4f[ 4] = decal->color4ub[1][0] * alpha;
9896                 c4f[ 5] = decal->color4ub[1][1] * alpha;
9897                 c4f[ 6] = decal->color4ub[1][2] * alpha;
9898                 c4f[ 7] = 1;
9899                 c4f[ 8] = decal->color4ub[2][0] * alpha;
9900                 c4f[ 9] = decal->color4ub[2][1] * alpha;
9901                 c4f[10] = decal->color4ub[2][2] * alpha;
9902                 c4f[11] = 1;
9903
9904                 t2f[0] = decal->texcoord2f[0][0];
9905                 t2f[1] = decal->texcoord2f[0][1];
9906                 t2f[2] = decal->texcoord2f[1][0];
9907                 t2f[3] = decal->texcoord2f[1][1];
9908                 t2f[4] = decal->texcoord2f[2][0];
9909                 t2f[5] = decal->texcoord2f[2][1];
9910
9911                 // update vertex positions for animated models
9912                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9913                 {
9914                         e = rsurface.modelelement3i + 3*decal->triangleindex;
9915                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9916                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9917                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9918                 }
9919                 else
9920                 {
9921                         VectorCopy(decal->vertex3f[0], v3f);
9922                         VectorCopy(decal->vertex3f[1], v3f + 3);
9923                         VectorCopy(decal->vertex3f[2], v3f + 6);
9924                 }
9925
9926                 v3f += 9;
9927                 c4f += 12;
9928                 t2f += 6;
9929                 numtris++;
9930         }
9931
9932         if (numtris > 0)
9933         {
9934                 r_refdef.stats.drawndecals += numtris;
9935
9936                 if (r_refdef.fogenabled)
9937                 {
9938                         switch(vid.renderpath)
9939                         {
9940                         case RENDERPATH_GL20:
9941                         case RENDERPATH_CGGL:
9942                         case RENDERPATH_GL13:
9943                         case RENDERPATH_GL11:
9944                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
9945                                 {
9946                                         alpha = RSurf_FogVertex(v3f);
9947                                         c4f[0] *= alpha;
9948                                         c4f[1] *= alpha;
9949                                         c4f[2] *= alpha;
9950                                 }
9951                                 break;
9952                         }
9953                 }
9954
9955                 // now render the decals all at once
9956                 // (this assumes they all use one particle font texture!)
9957                 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);
9958                 R_Mesh_ResetTextureState();
9959                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9960                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9961                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9962                 GL_DepthMask(false);
9963                 GL_DepthRange(0, 1);
9964                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9965                 GL_DepthTest(true);
9966                 GL_CullFace(GL_NONE);
9967                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9968                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
9969                 GL_LockArrays(0, numtris * 3);
9970                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9971                 GL_LockArrays(0, 0);
9972         }
9973 }
9974
9975 static void R_DrawModelDecals(void)
9976 {
9977         int i, numdecals;
9978
9979         // fade faster when there are too many decals
9980         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9981         for (i = 0;i < r_refdef.scene.numentities;i++)
9982                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9983
9984         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9985         for (i = 0;i < r_refdef.scene.numentities;i++)
9986                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9987                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9988
9989         R_DecalSystem_ApplySplatEntitiesQueue();
9990
9991         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9992         for (i = 0;i < r_refdef.scene.numentities;i++)
9993                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9994
9995         r_refdef.stats.totaldecals += numdecals;
9996
9997         if (r_showsurfaces.integer)
9998                 return;
9999
10000         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10001
10002         for (i = 0;i < r_refdef.scene.numentities;i++)
10003         {
10004                 if (!r_refdef.viewcache.entityvisible[i])
10005                         continue;
10006                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10007                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10008         }
10009 }
10010
10011 void R_DrawDebugModel(void)
10012 {
10013         entity_render_t *ent = rsurface.entity;
10014         int i, j, k, l, flagsmask;
10015         const int *elements;
10016         q3mbrush_t *brush;
10017         const msurface_t *surface;
10018         dp_model_t *model = ent->model;
10019         vec3_t v;
10020
10021         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10022
10023         R_Mesh_ColorPointer(NULL, 0, 0);
10024         R_Mesh_ResetTextureState();
10025         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10026         GL_DepthRange(0, 1);
10027         GL_DepthTest(!r_showdisabledepthtest.integer);
10028         GL_DepthMask(false);
10029         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10030
10031         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
10032         {
10033                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10034                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
10035                 {
10036                         if (brush->colbrushf && brush->colbrushf->numtriangles)
10037                         {
10038                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
10039                                 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);
10040                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
10041                         }
10042                 }
10043                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
10044                 {
10045                         if (surface->num_collisiontriangles)
10046                         {
10047                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
10048                                 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);
10049                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
10050                         }
10051                 }
10052         }
10053
10054         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10055
10056         if (r_showtris.integer || r_shownormals.integer)
10057         {
10058                 if (r_showdisabledepthtest.integer)
10059                 {
10060                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10061                         GL_DepthMask(false);
10062                 }
10063                 else
10064                 {
10065                         GL_BlendFunc(GL_ONE, GL_ZERO);
10066                         GL_DepthMask(true);
10067                 }
10068                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10069                 {
10070                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10071                                 continue;
10072                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10073                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10074                         {
10075                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
10076                                 if (r_showtris.value > 0)
10077                                 {
10078                                         if (!rsurface.texture->currentlayers->depthmask)
10079                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10080                                         else if (ent == r_refdef.scene.worldentity)
10081                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10082                                         else
10083                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10084                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
10085                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
10086                                         R_Mesh_ColorPointer(NULL, 0, 0);
10087                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
10088                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10089                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
10090                                         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);
10091                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10092                                         CHECKGLERROR
10093                                 }
10094                                 if (r_shownormals.value < 0)
10095                                 {
10096                                         qglBegin(GL_LINES);
10097                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10098                                         {
10099                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10100                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10101                                                 qglVertex3f(v[0], v[1], v[2]);
10102                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
10103                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10104                                                 qglVertex3f(v[0], v[1], v[2]);
10105                                         }
10106                                         qglEnd();
10107                                         CHECKGLERROR
10108                                 }
10109                                 if (r_shownormals.value > 0)
10110                                 {
10111                                         qglBegin(GL_LINES);
10112                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10113                                         {
10114                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10115                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10116                                                 qglVertex3f(v[0], v[1], v[2]);
10117                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
10118                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10119                                                 qglVertex3f(v[0], v[1], v[2]);
10120                                         }
10121                                         qglEnd();
10122                                         CHECKGLERROR
10123                                         qglBegin(GL_LINES);
10124                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10125                                         {
10126                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10127                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10128                                                 qglVertex3f(v[0], v[1], v[2]);
10129                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
10130                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10131                                                 qglVertex3f(v[0], v[1], v[2]);
10132                                         }
10133                                         qglEnd();
10134                                         CHECKGLERROR
10135                                         qglBegin(GL_LINES);
10136                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10137                                         {
10138                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10139                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10140                                                 qglVertex3f(v[0], v[1], v[2]);
10141                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
10142                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10143                                                 qglVertex3f(v[0], v[1], v[2]);
10144                                         }
10145                                         qglEnd();
10146                                         CHECKGLERROR
10147                                 }
10148                         }
10149                 }
10150                 rsurface.texture = NULL;
10151         }
10152 }
10153
10154 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10155 int r_maxsurfacelist = 0;
10156 const msurface_t **r_surfacelist = NULL;
10157 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10158 {
10159         int i, j, endj, f, flagsmask;
10160         texture_t *t;
10161         dp_model_t *model = r_refdef.scene.worldmodel;
10162         msurface_t *surfaces;
10163         unsigned char *update;
10164         int numsurfacelist = 0;
10165         if (model == NULL)
10166                 return;
10167
10168         if (r_maxsurfacelist < model->num_surfaces)
10169         {
10170                 r_maxsurfacelist = model->num_surfaces;
10171                 if (r_surfacelist)
10172                         Mem_Free((msurface_t**)r_surfacelist);
10173                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10174         }
10175
10176         RSurf_ActiveWorldEntity();
10177
10178         surfaces = model->data_surfaces;
10179         update = model->brushq1.lightmapupdateflags;
10180
10181         // update light styles on this submodel
10182         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
10183         {
10184                 model_brush_lightstyleinfo_t *style;
10185                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10186                 {
10187                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
10188                         {
10189                                 int *list = style->surfacelist;
10190                                 style->value = r_refdef.scene.lightstylevalue[style->style];
10191                                 for (j = 0;j < style->numsurfaces;j++)
10192                                         update[list[j]] = true;
10193                         }
10194                 }
10195         }
10196
10197         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10198
10199         if (debug)
10200         {
10201                 R_DrawDebugModel();
10202                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10203                 return;
10204         }
10205
10206         f = 0;
10207         t = NULL;
10208         rsurface.uselightmaptexture = false;
10209         rsurface.texture = NULL;
10210         rsurface.rtlight = NULL;
10211         numsurfacelist = 0;
10212         // add visible surfaces to draw list
10213         for (i = 0;i < model->nummodelsurfaces;i++)
10214         {
10215                 j = model->sortedmodelsurfaces[i];
10216                 if (r_refdef.viewcache.world_surfacevisible[j])
10217                         r_surfacelist[numsurfacelist++] = surfaces + j;
10218         }
10219         // update lightmaps if needed
10220         if (update)
10221         {
10222                 int updated = 0;
10223                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10224                 {
10225                         if (r_refdef.viewcache.world_surfacevisible[j])
10226                         {
10227                                 if (update[j])
10228                                 {
10229                                         updated++;
10230                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
10231                                 }
10232                         }
10233                 }
10234                 if (updated)
10235                 {
10236                         int count = model->brushq3.num_mergedlightmaps;
10237                         for (i = 0;i < count;i++)
10238                         {
10239                                 if (model->brushq3.data_deluxemaps[i])
10240                                         R_FlushTexture(model->brushq3.data_deluxemaps[i]);
10241                                 if (model->brushq3.data_lightmaps[i])
10242                                         R_FlushTexture(model->brushq3.data_lightmaps[i]);
10243                         }
10244                 }
10245         }
10246         // don't do anything if there were no surfaces
10247         if (!numsurfacelist)
10248         {
10249                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10250                 return;
10251         }
10252         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
10253         GL_AlphaTest(false);
10254
10255         // add to stats if desired
10256         if (r_speeds.integer && !skysurfaces && !depthonly)
10257         {
10258                 r_refdef.stats.world_surfaces += numsurfacelist;
10259                 for (j = 0;j < numsurfacelist;j++)
10260                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
10261         }
10262
10263         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10264 }
10265
10266 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10267 {
10268         int i, j, endj, f, flagsmask;
10269         texture_t *t;
10270         dp_model_t *model = ent->model;
10271         msurface_t *surfaces;
10272         unsigned char *update;
10273         int numsurfacelist = 0;
10274         if (model == NULL)
10275                 return;
10276
10277         if (r_maxsurfacelist < model->num_surfaces)
10278         {
10279                 r_maxsurfacelist = model->num_surfaces;
10280                 if (r_surfacelist)
10281                         Mem_Free((msurface_t **)r_surfacelist);
10282                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10283         }
10284
10285         // if the model is static it doesn't matter what value we give for
10286         // wantnormals and wanttangents, so this logic uses only rules applicable
10287         // to a model, knowing that they are meaningless otherwise
10288         if (ent == r_refdef.scene.worldentity)
10289                 RSurf_ActiveWorldEntity();
10290         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10291                 RSurf_ActiveModelEntity(ent, false, false, false);
10292         else if (prepass)
10293                 RSurf_ActiveModelEntity(ent, true, true, true);
10294         else if (depthonly)
10295                 RSurf_ActiveModelEntity(ent, false, false, false);
10296         else
10297         {
10298                 switch (vid.renderpath)
10299                 {
10300                 case RENDERPATH_GL20:
10301                 case RENDERPATH_CGGL:
10302                         RSurf_ActiveModelEntity(ent, true, true, false);
10303                         break;
10304                 case RENDERPATH_GL13:
10305                 case RENDERPATH_GL11:
10306                         RSurf_ActiveModelEntity(ent, true, false, false);
10307                         break;
10308                 }
10309         }
10310
10311         surfaces = model->data_surfaces;
10312         update = model->brushq1.lightmapupdateflags;
10313
10314         // update light styles
10315         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
10316         {
10317                 model_brush_lightstyleinfo_t *style;
10318                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10319                 {
10320                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
10321                         {
10322                                 int *list = style->surfacelist;
10323                                 style->value = r_refdef.scene.lightstylevalue[style->style];
10324                                 for (j = 0;j < style->numsurfaces;j++)
10325                                         update[list[j]] = true;
10326                         }
10327                 }
10328         }
10329
10330         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10331
10332         if (debug)
10333         {
10334                 R_DrawDebugModel();
10335                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10336                 return;
10337         }
10338
10339         f = 0;
10340         t = NULL;
10341         rsurface.uselightmaptexture = false;
10342         rsurface.texture = NULL;
10343         rsurface.rtlight = NULL;
10344         numsurfacelist = 0;
10345         // add visible surfaces to draw list
10346         for (i = 0;i < model->nummodelsurfaces;i++)
10347                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
10348         // don't do anything if there were no surfaces
10349         if (!numsurfacelist)
10350         {
10351                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10352                 return;
10353         }
10354         // update lightmaps if needed
10355         if (update)
10356         {
10357                 int updated = 0;
10358                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10359                 {
10360                         if (update[j])
10361                         {
10362                                 updated++;
10363                                 R_BuildLightMap(ent, surfaces + j);
10364                         }
10365                 }
10366                 if (updated)
10367                 {
10368                         int count = model->brushq3.num_mergedlightmaps;
10369                         for (i = 0;i < count;i++)
10370                         {
10371                                 if (model->brushq3.data_deluxemaps[i])
10372                                         R_FlushTexture(model->brushq3.data_deluxemaps[i]);
10373                                 if (model->brushq3.data_lightmaps[i])
10374                                         R_FlushTexture(model->brushq3.data_lightmaps[i]);
10375                         }
10376                 }
10377         }
10378         if (update)
10379                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10380                         if (update[j])
10381                                 R_BuildLightMap(ent, surfaces + j);
10382         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
10383         GL_AlphaTest(false);
10384
10385         // add to stats if desired
10386         if (r_speeds.integer && !skysurfaces && !depthonly)
10387         {
10388                 r_refdef.stats.entities_surfaces += numsurfacelist;
10389                 for (j = 0;j < numsurfacelist;j++)
10390                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
10391         }
10392
10393         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10394 }
10395
10396 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
10397 {
10398         static texture_t texture;
10399         static msurface_t surface;
10400         const msurface_t *surfacelist = &surface;
10401
10402         // fake enough texture and surface state to render this geometry
10403
10404         texture.update_lastrenderframe = -1; // regenerate this texture
10405         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
10406         texture.currentskinframe = skinframe;
10407         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
10408         texture.specularscalemod = 1;
10409         texture.specularpowermod = 1;
10410
10411         surface.texture = &texture;
10412         surface.num_triangles = numtriangles;
10413         surface.num_firsttriangle = firsttriangle;
10414         surface.num_vertices = numvertices;
10415         surface.num_firstvertex = firstvertex;
10416
10417         // now render it
10418         rsurface.texture = R_GetCurrentTexture(surface.texture);
10419         rsurface.uselightmaptexture = false;
10420         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10421 }
10422
10423 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)
10424 {
10425         static msurface_t surface;
10426         const msurface_t *surfacelist = &surface;
10427
10428         // fake enough texture and surface state to render this geometry
10429
10430         surface.texture = texture;
10431         surface.num_triangles = numtriangles;
10432         surface.num_firsttriangle = firsttriangle;
10433         surface.num_vertices = numvertices;
10434         surface.num_firstvertex = firstvertex;
10435
10436         // now render it
10437         rsurface.texture = R_GetCurrentTexture(surface.texture);
10438         rsurface.uselightmaptexture = false;
10439         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10440 }