]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
d45a0eef68132901ad828bcde10718d667434964
[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
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
30
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
32
33 qboolean r_loadnormalmap;
34 qboolean r_loadgloss;
35 qboolean r_loadfog;
36
37 //
38 // screen size info
39 //
40 r_refdef_t r_refdef;
41
42 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
43 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
44 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
45 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
46 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)"};
47 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
48 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
49 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
50
51 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
52 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"};
53 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
54 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)"};
55 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
56
57 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"};
58 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
59 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
60 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
61 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
62 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
63 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)"};
64 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
65 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
66 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"};
67 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"};
68 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
69 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"};
70 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"};
71 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"};
72 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
73 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
74 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
75 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
76 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)"};
77 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)"};
78 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
79 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
80 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
81 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
82 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
83 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
84 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
85 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."};
86 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
87 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
88 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
89 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."};
90 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
91 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
92 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"};
93 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"};
94 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
95 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
96 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
97 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
98 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"};
99
100 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
101 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
102 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
103 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
104 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
105 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
106 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
107 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
108
109 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
110 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
111 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
112
113 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)"};
114 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
115 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
116 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
117 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
118 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)"};
119 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)"};
120 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)"};
121 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)"};
122
123 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)"};
124 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
125 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"};
126 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
127 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
128
129 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
130 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
131 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
132 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
133
134 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
135 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
136 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
137 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
138 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
139 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
140 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
141
142 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
143 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
144 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
145 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)"};
146
147 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"};
148
149 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"};
150
151 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
152
153 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
154 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
155 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"};
156 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
157 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
158 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
159 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
160
161 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)"};
162
163 extern cvar_t v_glslgamma;
164
165 extern qboolean v_flipped_state;
166
167 static struct r_bloomstate_s
168 {
169         qboolean enabled;
170         qboolean hdr;
171
172         int bloomwidth, bloomheight;
173
174         int screentexturewidth, screentextureheight;
175         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
176
177         int bloomtexturewidth, bloomtextureheight;
178         rtexture_t *texture_bloom;
179
180         // arrays for rendering the screen passes
181         float screentexcoord2f[8];
182         float bloomtexcoord2f[8];
183         float offsettexcoord2f[8];
184
185         r_viewport_t viewport;
186 }
187 r_bloomstate;
188
189 r_waterstate_t r_waterstate;
190
191 /// shadow volume bsp struct with automatically growing nodes buffer
192 svbsp_t r_svbsp;
193
194 rtexture_t *r_texture_blanknormalmap;
195 rtexture_t *r_texture_white;
196 rtexture_t *r_texture_grey128;
197 rtexture_t *r_texture_black;
198 rtexture_t *r_texture_notexture;
199 rtexture_t *r_texture_whitecube;
200 rtexture_t *r_texture_normalizationcube;
201 rtexture_t *r_texture_fogattenuation;
202 rtexture_t *r_texture_gammaramps;
203 unsigned int r_texture_gammaramps_serial;
204 //rtexture_t *r_texture_fogintensity;
205
206 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
207 unsigned int r_numqueries;
208 unsigned int r_maxqueries;
209
210 typedef struct r_qwskincache_s
211 {
212         char name[MAX_QPATH];
213         skinframe_t *skinframe;
214 }
215 r_qwskincache_t;
216
217 static r_qwskincache_t *r_qwskincache;
218 static int r_qwskincache_size;
219
220 /// vertex coordinates for a quad that covers the screen exactly
221 const float r_screenvertex3f[12] =
222 {
223         0, 0, 0,
224         1, 0, 0,
225         1, 1, 0,
226         0, 1, 0
227 };
228
229 extern void R_DrawModelShadows(void);
230
231 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
232 {
233         int i;
234         for (i = 0;i < verts;i++)
235         {
236                 out[0] = in[0] * r;
237                 out[1] = in[1] * g;
238                 out[2] = in[2] * b;
239                 out[3] = in[3];
240                 in += 4;
241                 out += 4;
242         }
243 }
244
245 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
246 {
247         int i;
248         for (i = 0;i < verts;i++)
249         {
250                 out[0] = r;
251                 out[1] = g;
252                 out[2] = b;
253                 out[3] = a;
254                 out += 4;
255         }
256 }
257
258 // FIXME: move this to client?
259 void FOG_clear(void)
260 {
261         if (gamemode == GAME_NEHAHRA)
262         {
263                 Cvar_Set("gl_fogenable", "0");
264                 Cvar_Set("gl_fogdensity", "0.2");
265                 Cvar_Set("gl_fogred", "0.3");
266                 Cvar_Set("gl_foggreen", "0.3");
267                 Cvar_Set("gl_fogblue", "0.3");
268         }
269         r_refdef.fog_density = 0;
270         r_refdef.fog_red = 0;
271         r_refdef.fog_green = 0;
272         r_refdef.fog_blue = 0;
273         r_refdef.fog_alpha = 1;
274         r_refdef.fog_start = 0;
275         r_refdef.fog_end = 16384;
276         r_refdef.fog_height = 1<<30;
277         r_refdef.fog_fadedepth = 128;
278 }
279
280 static void R_BuildBlankTextures(void)
281 {
282         unsigned char data[4];
283         data[2] = 128; // normal X
284         data[1] = 128; // normal Y
285         data[0] = 255; // normal Z
286         data[3] = 128; // height
287         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
288         data[0] = 255;
289         data[1] = 255;
290         data[2] = 255;
291         data[3] = 255;
292         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
293         data[0] = 128;
294         data[1] = 128;
295         data[2] = 128;
296         data[3] = 255;
297         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
298         data[0] = 0;
299         data[1] = 0;
300         data[2] = 0;
301         data[3] = 255;
302         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
303 }
304
305 static void R_BuildNoTexture(void)
306 {
307         int x, y;
308         unsigned char pix[16][16][4];
309         // this makes a light grey/dark grey checkerboard texture
310         for (y = 0;y < 16;y++)
311         {
312                 for (x = 0;x < 16;x++)
313                 {
314                         if ((y < 8) ^ (x < 8))
315                         {
316                                 pix[y][x][0] = 128;
317                                 pix[y][x][1] = 128;
318                                 pix[y][x][2] = 128;
319                                 pix[y][x][3] = 255;
320                         }
321                         else
322                         {
323                                 pix[y][x][0] = 64;
324                                 pix[y][x][1] = 64;
325                                 pix[y][x][2] = 64;
326                                 pix[y][x][3] = 255;
327                         }
328                 }
329         }
330         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
331 }
332
333 static void R_BuildWhiteCube(void)
334 {
335         unsigned char data[6*1*1*4];
336         memset(data, 255, sizeof(data));
337         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
338 }
339
340 static void R_BuildNormalizationCube(void)
341 {
342         int x, y, side;
343         vec3_t v;
344         vec_t s, t, intensity;
345 #define NORMSIZE 64
346         unsigned char *data;
347         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
348         for (side = 0;side < 6;side++)
349         {
350                 for (y = 0;y < NORMSIZE;y++)
351                 {
352                         for (x = 0;x < NORMSIZE;x++)
353                         {
354                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
355                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
356                                 switch(side)
357                                 {
358                                 default:
359                                 case 0:
360                                         v[0] = 1;
361                                         v[1] = -t;
362                                         v[2] = -s;
363                                         break;
364                                 case 1:
365                                         v[0] = -1;
366                                         v[1] = -t;
367                                         v[2] = s;
368                                         break;
369                                 case 2:
370                                         v[0] = s;
371                                         v[1] = 1;
372                                         v[2] = t;
373                                         break;
374                                 case 3:
375                                         v[0] = s;
376                                         v[1] = -1;
377                                         v[2] = -t;
378                                         break;
379                                 case 4:
380                                         v[0] = s;
381                                         v[1] = -t;
382                                         v[2] = 1;
383                                         break;
384                                 case 5:
385                                         v[0] = -s;
386                                         v[1] = -t;
387                                         v[2] = -1;
388                                         break;
389                                 }
390                                 intensity = 127.0f / sqrt(DotProduct(v, v));
391                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
392                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
393                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
394                                 data[((side*64+y)*64+x)*4+3] = 255;
395                         }
396                 }
397         }
398         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
399         Mem_Free(data);
400 }
401
402 static void R_BuildFogTexture(void)
403 {
404         int x, b;
405 #define FOGWIDTH 256
406         unsigned char data1[FOGWIDTH][4];
407         //unsigned char data2[FOGWIDTH][4];
408         double d, r, alpha;
409
410         r_refdef.fogmasktable_start = r_refdef.fog_start;
411         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
412         r_refdef.fogmasktable_range = r_refdef.fogrange;
413         r_refdef.fogmasktable_density = r_refdef.fog_density;
414
415         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
416         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
417         {
418                 d = (x * r - r_refdef.fogmasktable_start);
419                 if(developer.integer >= 100)
420                         Con_Printf("%f ", d);
421                 d = max(0, d);
422                 if (r_fog_exp2.integer)
423                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
424                 else
425                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
426                 if(developer.integer >= 100)
427                         Con_Printf(" : %f ", alpha);
428                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
429                 if(developer.integer >= 100)
430                         Con_Printf(" = %f\n", alpha);
431                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
432         }
433
434         for (x = 0;x < FOGWIDTH;x++)
435         {
436                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
437                 data1[x][0] = b;
438                 data1[x][1] = b;
439                 data1[x][2] = b;
440                 data1[x][3] = 255;
441                 //data2[x][0] = 255 - b;
442                 //data2[x][1] = 255 - b;
443                 //data2[x][2] = 255 - b;
444                 //data2[x][3] = 255;
445         }
446         if (r_texture_fogattenuation)
447         {
448                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
449                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
450         }
451         else
452         {
453                 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);
454                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
455         }
456 }
457
458 static const char *builtinshaderstring =
459 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
460 "// written by Forest 'LordHavoc' Hale\n"
461 "\n"
462 "// enable various extensions depending on permutation:\n"
463 "\n"
464 "#ifdef VERTEX_SHADER\n"
465 "uniform mat4 ModelViewProjectionMatrix;\n"
466 "#endif\n"
467 "\n"
468 "#ifdef MODE_DEPTH_OR_SHADOW\n"
469 "#ifdef VERTEX_SHADER\n"
470 "void main(void)\n"
471 "{\n"
472 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
473 "}\n"
474 "#endif\n"
475 "#else // !MODE_DEPTH_ORSHADOW\n"
476 "#ifdef MODE_SHOWDEPTH\n"
477 "#ifdef VERTEX_SHADER\n"
478 "void main(void)\n"
479 "{\n"
480 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
481 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
482 "}\n"
483 "#endif\n"
484 "\n"
485 "#ifdef FRAGMENT_SHADER\n"
486 "void main(void)\n"
487 "{\n"
488 "       gl_FragColor = gl_Color;\n"
489 "}\n"
490 "#endif\n"
491 "#else // !MODE_SHOWDEPTH\n"
492 "#ifdef MODE_POSTPROCESS\n"
493 "varying vec2 TexCoord1;\n"
494 "varying vec2 TexCoord2;\n"
495 "\n"
496 "#ifdef VERTEX_SHADER\n"
497 "void main(void)\n"
498 "{\n"
499 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
500 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
501 "#ifdef USEBLOOM\n"
502 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
503 "#endif\n"
504 "}\n"
505 "#endif\n"
506 "\n"
507 "#ifdef FRAGMENT_SHADER\n"
508 "uniform sampler2D Texture_First;\n"
509 "#ifdef USEBLOOM\n"
510 "uniform sampler2D Texture_Second;\n"
511 "#endif\n"
512 "#ifdef USEGAMMARAMPS\n"
513 "uniform sampler2D Texture_GammaRamps;\n"
514 "#endif\n"
515 "#ifdef USESATURATION\n"
516 "uniform float Saturation;\n"
517 "#endif\n"
518 "#ifdef USEVIEWTINT\n"
519 "uniform vec4 ViewTintColor;\n"
520 "#endif\n"
521 "//uncomment these if you want to use them:\n"
522 "uniform vec4 UserVec1;\n"
523 "// uniform vec4 UserVec2;\n"
524 "// uniform vec4 UserVec3;\n"
525 "// uniform vec4 UserVec4;\n"
526 "// uniform float ClientTime;\n"
527 "uniform vec2 PixelSize;\n"
528 "void main(void)\n"
529 "{\n"
530 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
531 "#ifdef USEBLOOM\n"
532 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
533 "#endif\n"
534 "#ifdef USEVIEWTINT\n"
535 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
536 "#endif\n"
537 "\n"
538 "#ifdef USEPOSTPROCESSING\n"
539 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
540 "// 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"
541 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
542 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
543 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
544 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
545 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
546 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
547 "#endif\n"
548 "\n"
549 "#ifdef USESATURATION\n"
550 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
551 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
552 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
553 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
554 "#endif\n"
555 "\n"
556 "#ifdef USEGAMMARAMPS\n"
557 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
558 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
559 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
560 "#endif\n"
561 "}\n"
562 "#endif\n"
563 "#else // !MODE_POSTPROCESS\n"
564 "#ifdef MODE_GENERIC\n"
565 "#ifdef USEDIFFUSE\n"
566 "varying vec2 TexCoord1;\n"
567 "#endif\n"
568 "#ifdef USESPECULAR\n"
569 "varying vec2 TexCoord2;\n"
570 "#endif\n"
571 "#ifdef VERTEX_SHADER\n"
572 "void main(void)\n"
573 "{\n"
574 "       gl_FrontColor = gl_Color;\n"
575 "#ifdef USEDIFFUSE\n"
576 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
577 "#endif\n"
578 "#ifdef USESPECULAR\n"
579 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
580 "#endif\n"
581 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
582 "}\n"
583 "#endif\n"
584 "\n"
585 "#ifdef FRAGMENT_SHADER\n"
586 "#ifdef USEDIFFUSE\n"
587 "uniform sampler2D Texture_First;\n"
588 "#endif\n"
589 "#ifdef USESPECULAR\n"
590 "uniform sampler2D Texture_Second;\n"
591 "#endif\n"
592 "\n"
593 "void main(void)\n"
594 "{\n"
595 "       gl_FragColor = gl_Color;\n"
596 "#ifdef USEDIFFUSE\n"
597 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
598 "#endif\n"
599 "\n"
600 "#ifdef USESPECULAR\n"
601 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
602 "# ifdef USECOLORMAPPING\n"
603 "       gl_FragColor *= tex2;\n"
604 "# endif\n"
605 "# ifdef USEGLOW\n"
606 "       gl_FragColor += tex2;\n"
607 "# endif\n"
608 "# ifdef USEVERTEXTEXTUREBLEND\n"
609 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
610 "# endif\n"
611 "#endif\n"
612 "}\n"
613 "#endif\n"
614 "#else // !MODE_GENERIC\n"
615 "#ifdef MODE_BLOOMBLUR\n"
616 "varying TexCoord;\n"
617 "#ifdef VERTEX_SHADER\n"
618 "void main(void)\n"
619 "{\n"
620 "       gl_FrontColor = gl_Color;\n"
621 "       TexCoord = gl_MultiTexCoord0.xy;\n"
622 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
623 "}\n"
624 "#endif\n"
625 "\n"
626 "#ifdef FRAGMENT_SHADER\n"
627 "uniform sampler2D Texture_First;\n"
628 "uniform vec4 BloomBlur_Parameters;\n"
629 "\n"
630 "void main(void)\n"
631 "{\n"
632 "       int i;\n"
633 "       vec2 tc = TexCoord;\n"
634 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
635 "       tc += BloomBlur_Parameters.xy;\n"
636 "       for (i = 1;i < SAMPLES;i++)\n"
637 "       {\n"
638 "               color += texture2D(Texture_First, tc).rgb;\n"
639 "               tc += BloomBlur_Parameters.xy;\n"
640 "       }\n"
641 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
642 "}\n"
643 "#endif\n"
644 "#else // !MODE_BLOOMBLUR\n"
645 "#ifdef MODE_REFRACTION\n"
646 "varying vec2 TexCoord;\n"
647 "varying vec4 ModelViewProjectionPosition;\n"
648 "uniform mat4 TexMatrix;\n"
649 "#ifdef VERTEX_SHADER\n"
650 "\n"
651 "void main(void)\n"
652 "{\n"
653 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
654 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
655 "       ModelViewProjectionPosition = gl_Position;\n"
656 "}\n"
657 "#endif\n"
658 "\n"
659 "#ifdef FRAGMENT_SHADER\n"
660 "uniform sampler2D Texture_Normal;\n"
661 "uniform sampler2D Texture_Refraction;\n"
662 "uniform sampler2D Texture_Reflection;\n"
663 "\n"
664 "uniform vec4 DistortScaleRefractReflect;\n"
665 "uniform vec4 ScreenScaleRefractReflect;\n"
666 "uniform vec4 ScreenCenterRefractReflect;\n"
667 "uniform vec4 RefractColor;\n"
668 "uniform vec4 ReflectColor;\n"
669 "uniform float ReflectFactor;\n"
670 "uniform float ReflectOffset;\n"
671 "\n"
672 "void main(void)\n"
673 "{\n"
674 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
675 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
676 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
677 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
678 "       // FIXME temporary hack to detect the case that the reflection\n"
679 "       // gets blackened at edges due to leaving the area that contains actual\n"
680 "       // content.\n"
681 "       // Remove this 'ack once we have a better way to stop this thing from\n"
682 "       // 'appening.\n"
683 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
684 "       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 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
688 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
689 "}\n"
690 "#endif\n"
691 "#else // !MODE_REFRACTION\n"
692 "#ifdef MODE_WATER\n"
693 "varying vec2 TexCoord;\n"
694 "varying vec3 EyeVector;\n"
695 "varying vec4 ModelViewProjectionPosition;\n"
696 "#ifdef VERTEX_SHADER\n"
697 "uniform vec3 EyePosition;\n"
698 "uniform mat4 TexMatrix;\n"
699 "\n"
700 "void main(void)\n"
701 "{\n"
702 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
703 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
704 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
705 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
706 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
707 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
708 "       ModelViewProjectionPosition = gl_Position;\n"
709 "}\n"
710 "#endif\n"
711 "\n"
712 "#ifdef FRAGMENT_SHADER\n"
713 "uniform sampler2D Texture_Normal;\n"
714 "uniform sampler2D Texture_Refraction;\n"
715 "uniform sampler2D Texture_Reflection;\n"
716 "\n"
717 "uniform vec4 DistortScaleRefractReflect;\n"
718 "uniform vec4 ScreenScaleRefractReflect;\n"
719 "uniform vec4 ScreenCenterRefractReflect;\n"
720 "uniform vec4 RefractColor;\n"
721 "uniform vec4 ReflectColor;\n"
722 "uniform float ReflectFactor;\n"
723 "uniform float ReflectOffset;\n"
724 "\n"
725 "void main(void)\n"
726 "{\n"
727 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
728 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
729 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
730 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
731 "       // FIXME temporary hack to detect the case that the reflection\n"
732 "       // gets blackened at edges due to leaving the area that contains actual\n"
733 "       // content.\n"
734 "       // Remove this 'ack once we have a better way to stop this thing from\n"
735 "       // 'appening.\n"
736 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
737 "       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 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
741 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\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 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
746 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
747 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
748 "}\n"
749 "#endif\n"
750 "#else // !MODE_WATER\n"
751 "\n"
752 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
753 "# extension GL_ARB_texture_rectangle : enable\n"
754 "#endif\n"
755 "\n"
756 "#ifdef USESHADOWMAP2D\n"
757 "# ifdef GL_EXT_gpu_shader4\n"
758 "#   extension GL_EXT_gpu_shader4 : enable\n"
759 "# endif\n"
760 "# ifdef GL_ARB_texture_gather\n"
761 "#   extension GL_ARB_texture_gather : enable\n"
762 "# else\n"
763 "#   ifdef GL_AMD_texture_texture4\n"
764 "#     extension GL_AMD_texture_texture4 : enable\n"
765 "#   endif\n"
766 "# endif\n"
767 "#endif\n"
768 "\n"
769 "#ifdef USESHADOWMAPCUBE\n"
770 "# extension GL_EXT_gpu_shader4 : enable\n"
771 "#endif\n"
772 "\n"
773 "#ifdef USESHADOWSAMPLER\n"
774 "# extension GL_ARB_shadow : enable\n"
775 "#endif\n"
776 "\n"
777 "// common definitions between vertex shader and fragment shader:\n"
778 "\n"
779 "//#ifdef __GLSL_CG_DATA_TYPES\n"
780 "//# define myhalf half\n"
781 "//# define myhalf2 half2\n"
782 "//# define myhalf3half3\n"
783 "//# define myhalf4 half4\n"
784 "//#else\n"
785 "# define myhalf float\n"
786 "# define myhalf2 vec2\n"
787 "# define myhalf3 vec3\n"
788 "# define myhalf4 vec4\n"
789 "//#endif\n"
790 "\n"
791 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
792 "# define USEFOG\n"
793 "#endif\n"
794 "\n"
795 "varying vec2 TexCoord;\n"
796 "#ifdef USEVERTEXTEXTUREBLEND\n"
797 "varying vec2 TexCoord2;\n"
798 "#endif\n"
799 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
800 "#define USELIGHTMAP\n"
801 "varying vec2 TexCoordLightmap;\n"
802 "#endif\n"
803 "\n"
804 "#ifdef MODE_LIGHTSOURCE\n"
805 "varying vec3 CubeVector;\n"
806 "#endif\n"
807 "\n"
808 "#ifdef MODE_LIGHTSOURCE\n"
809 "varying vec3 LightVector;\n"
810 "#endif\n"
811 "#if defined(MODE_LIGHTDIRECTION)\n"
812 "varying vec3 LightVector;\n"
813 "#endif\n"
814 "\n"
815 "#if defined(USEOFFSETMAPPING) || defined(USESPECULAR)\n"
816 "//#if defined(USEOFFSETMAPPING) || defined(USESPECULAR) || defined(MODE_LIGHTDIRECTION) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
817 "#define USEEYEVECTOR\n"
818 "varying vec3 EyeVector;\n"
819 "#endif\n"
820 "#ifdef USEFOG\n"
821 "varying vec3 EyeVectorModelSpace;\n"
822 "varying float FogPlaneVertexDist;\n"
823 "#endif\n"
824 "\n"
825 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
826 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
827 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
828 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
829 "#endif\n"
830 "\n"
831 "#ifdef USEREFLECTION\n"
832 "varying vec4 ModelViewProjectionPosition;\n"
833 "#endif\n"
834 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
835 "uniform vec3 LightPosition;\n"
836 "varying vec4 ModelViewPosition;\n"
837 "#endif\n"
838 "\n"
839 "#ifdef MODE_LIGHTSOURCE\n"
840 "uniform vec3 LightPosition;\n"
841 "#endif\n"
842 "uniform vec3 EyePosition;\n"
843 "#ifdef MODE_LIGHTDIRECTION\n"
844 "uniform vec3 LightDir;\n"
845 "#endif\n"
846 "uniform vec4 FogPlane;\n"
847 "\n"
848 "\n"
849 "\n"
850 "\n"
851 "\n"
852 "// vertex shader specific:\n"
853 "#ifdef VERTEX_SHADER\n"
854 "\n"
855 "// 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"
856 "\n"
857 "#ifdef MODE_DEFERREDGEOMETRY\n"
858 "uniform mat4 TexMatrix;\n"
859 "#ifdef USEVERTEXTEXTUREBLEND\n"
860 "uniform mat4 BackgroundTexMatrix;\n"
861 "#endif\n"
862 "uniform mat4 ModelViewMatrix;\n"
863 "void main(void)\n"
864 "{\n"
865 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
866 "#ifdef USEVERTEXTEXTUREBLEND\n"
867 "       gl_FrontColor = gl_Color;\n"
868 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
869 "#endif\n"
870 "\n"
871 "       // transform unnormalized eye direction into tangent space\n"
872 "#ifdef USEOFFSETMAPPING\n"
873 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
874 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
875 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
876 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
877 "#endif\n"
878 "\n"
879 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
880 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
881 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
882 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
883 "}\n"
884 "#else // !MODE_DEFERREDGEOMETRY\n"
885 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
886 "uniform mat4 ModelViewMatrix;\n"
887 "void main(void)\n"
888 "{\n"
889 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
890 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
891 "}\n"
892 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
893 "uniform mat4 TexMatrix;\n"
894 "#ifdef USEVERTEXTEXTUREBLEND\n"
895 "uniform mat4 BackgroundTexMatrix;\n"
896 "#endif\n"
897 "#ifdef MODE_LIGHTSOURCE\n"
898 "uniform mat4 ModelToLight;\n"
899 "#endif\n"
900 "void main(void)\n"
901 "{\n"
902 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
903 "       gl_FrontColor = gl_Color;\n"
904 "#endif\n"
905 "       // copy the surface texcoord\n"
906 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
907 "#ifdef USEVERTEXTEXTUREBLEND\n"
908 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
909 "#endif\n"
910 "#ifdef USELIGHTMAP\n"
911 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
912 "#endif\n"
913 "\n"
914 "#ifdef MODE_LIGHTSOURCE\n"
915 "       // transform vertex position into light attenuation/cubemap space\n"
916 "       // (-1 to +1 across the light box)\n"
917 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
918 "\n"
919 "# ifdef USEDIFFUSE\n"
920 "       // transform unnormalized light direction into tangent space\n"
921 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
922 "       //  normalize it per pixel)\n"
923 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
924 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
925 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
926 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
927 "# endif\n"
928 "#endif\n"
929 "\n"
930 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
931 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
932 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
933 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
934 "#endif\n"
935 "\n"
936 "       // transform unnormalized eye direction into tangent space\n"
937 "#ifdef USEEYEVECTOR\n"
938 "#ifndef USEFOG\n"
939 "       vec3 EyeVectorModelSpace;\n"
940 "#endif\n"
941 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
942 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
943 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
944 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
945 "#endif\n"
946 "\n"
947 "#ifdef USEFOG\n"
948 "#ifndef USEEYEVECTOR\n"
949 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
950 "#endif\n"
951 "       FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
952 "#endif\n"
953 "\n"
954 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
955 "       VectorS = gl_MultiTexCoord1.xyz;\n"
956 "       VectorT = gl_MultiTexCoord2.xyz;\n"
957 "       VectorR = gl_MultiTexCoord3.xyz;\n"
958 "#endif\n"
959 "\n"
960 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
961 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
962 "\n"
963 "#ifdef USEREFLECTION\n"
964 "       ModelViewProjectionPosition = gl_Position;\n"
965 "#endif\n"
966 "}\n"
967 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
968 "#endif // !MODE_DEFERREDGEOMETRY\n"
969 "\n"
970 "#endif // VERTEX_SHADER\n"
971 "\n"
972 "\n"
973 "\n"
974 "\n"
975 "// fragment shader specific:\n"
976 "#ifdef FRAGMENT_SHADER\n"
977 "\n"
978 "uniform sampler2D Texture_Normal;\n"
979 "uniform sampler2D Texture_Color;\n"
980 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
981 "uniform sampler2D Texture_Gloss;\n"
982 "//#endif\n"
983 "#ifdef USEGLOW\n"
984 "uniform sampler2D Texture_Glow;\n"
985 "#endif\n"
986 "#ifdef USEVERTEXTEXTUREBLEND\n"
987 "uniform sampler2D Texture_SecondaryNormal;\n"
988 "uniform sampler2D Texture_SecondaryColor;\n"
989 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
990 "uniform sampler2D Texture_SecondaryGloss;\n"
991 "//#endif\n"
992 "#ifdef USEGLOW\n"
993 "uniform sampler2D Texture_SecondaryGlow;\n"
994 "#endif\n"
995 "#endif\n"
996 "#ifdef USECOLORMAPPING\n"
997 "uniform sampler2D Texture_Pants;\n"
998 "uniform sampler2D Texture_Shirt;\n"
999 "#endif\n"
1000 "#ifdef USEFOG\n"
1001 "uniform sampler2D Texture_FogMask;\n"
1002 "#endif\n"
1003 "#ifdef USELIGHTMAP\n"
1004 "uniform sampler2D Texture_Lightmap;\n"
1005 "#endif\n"
1006 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1007 "uniform sampler2D Texture_Deluxemap;\n"
1008 "#endif\n"
1009 "#ifdef USEREFLECTION\n"
1010 "uniform sampler2D Texture_Reflection;\n"
1011 "#endif\n"
1012 "\n"
1013 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1014 "uniform sampler2DRect Texture_ScreenDepth;\n"
1015 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
1016 "#endif\n"
1017 "#ifdef USEDEFERREDLIGHTMAP\n"
1018 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
1019 "uniform sampler2DRect Texture_ScreenSpecular;\n"
1020 "#endif\n"
1021 "\n"
1022 "uniform myhalf3 Color_Pants;\n"
1023 "uniform myhalf3 Color_Shirt;\n"
1024 "uniform myhalf3 FogColor;\n"
1025 "\n"
1026 "#ifdef USEFOG\n"
1027 "uniform float FogRangeRecip;\n"
1028 "uniform float FogPlaneViewDist;\n"
1029 "uniform float FogHeightFade;\n"
1030 "myhalf FogVertex(void)\n"
1031 "{\n"
1032 "       float fogfrac;\n"
1033 "#ifdef USEFOGOUTSIDE\n"
1034 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1035 "#else\n"
1036 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1037 "#endif\n"
1038 "       return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1039 "}\n"
1040 "#endif\n"
1041 "\n"
1042 "#ifdef USEOFFSETMAPPING\n"
1043 "uniform float OffsetMapping_Scale;\n"
1044 "vec2 OffsetMapping(vec2 TexCoord)\n"
1045 "{\n"
1046 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1047 "       // 14 sample relief mapping: linear search and then binary search\n"
1048 "       // this basically steps forward a small amount repeatedly until it finds\n"
1049 "       // itself inside solid, then jitters forward and back using decreasing\n"
1050 "       // amounts to find the impact\n"
1051 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1052 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1053 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1054 "       vec3 RT = vec3(TexCoord, 1);\n"
1055 "       OffsetVector *= 0.1;\n"
1056 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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)          - 0.5);\n"
1066 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1067 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1068 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1069 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1070 "       return RT.xy;\n"
1071 "#else\n"
1072 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1073 "       // this basically moves forward the full distance, and then backs up based\n"
1074 "       // on height of samples\n"
1075 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1076 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1077 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1078 "       TexCoord += OffsetVector;\n"
1079 "       OffsetVector *= 0.333;\n"
1080 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1081 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1082 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1083 "       return TexCoord;\n"
1084 "#endif\n"
1085 "}\n"
1086 "#endif // USEOFFSETMAPPING\n"
1087 "\n"
1088 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1089 "uniform sampler2D Texture_Attenuation;\n"
1090 "uniform samplerCube Texture_Cube;\n"
1091 "\n"
1092 "#ifdef USESHADOWMAPRECT\n"
1093 "# ifdef USESHADOWSAMPLER\n"
1094 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1095 "# else\n"
1096 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1097 "# endif\n"
1098 "#endif\n"
1099 "\n"
1100 "#ifdef USESHADOWMAP2D\n"
1101 "# ifdef USESHADOWSAMPLER\n"
1102 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1103 "# else\n"
1104 "uniform sampler2D Texture_ShadowMap2D;\n"
1105 "# endif\n"
1106 "#endif\n"
1107 "\n"
1108 "#ifdef USESHADOWMAPVSDCT\n"
1109 "uniform samplerCube Texture_CubeProjection;\n"
1110 "#endif\n"
1111 "\n"
1112 "#ifdef USESHADOWMAPCUBE\n"
1113 "# ifdef USESHADOWSAMPLER\n"
1114 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1115 "# else\n"
1116 "uniform samplerCube Texture_ShadowMapCube;\n"
1117 "# endif\n"
1118 "#endif\n"
1119 "\n"
1120 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1121 "uniform vec2 ShadowMap_TextureScale;\n"
1122 "uniform vec4 ShadowMap_Parameters;\n"
1123 "#endif\n"
1124 "\n"
1125 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1126 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1127 "{\n"
1128 "       vec3 adir = abs(dir);\n"
1129 "# ifndef USESHADOWMAPVSDCT\n"
1130 "       vec2 tc;\n"
1131 "       vec2 offset;\n"
1132 "       float ma;\n"
1133 "       if (adir.x > adir.y)\n"
1134 "       {\n"
1135 "               if (adir.x > adir.z) // X\n"
1136 "               {\n"
1137 "                       ma = adir.x;\n"
1138 "                       tc = dir.zy;\n"
1139 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1140 "               }\n"
1141 "               else // Z\n"
1142 "               {\n"
1143 "                       ma = adir.z;\n"
1144 "                       tc = dir.xy;\n"
1145 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1146 "               }\n"
1147 "       }\n"
1148 "       else\n"
1149 "       {\n"
1150 "               if (adir.y > adir.z) // Y\n"
1151 "               {\n"
1152 "                       ma = adir.y;\n"
1153 "                       tc = dir.xz;\n"
1154 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1155 "               }\n"
1156 "               else // Z\n"
1157 "               {\n"
1158 "                       ma = adir.z;\n"
1159 "                       tc = dir.xy;\n"
1160 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1161 "               }\n"
1162 "       }\n"
1163 "\n"
1164 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1165 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1166 "       stc.z += ShadowMap_Parameters.z;\n"
1167 "       return stc;\n"
1168 "# else\n"
1169 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1170 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1171 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1172 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1173 "       stc.z += ShadowMap_Parameters.z;\n"
1174 "       return stc;\n"
1175 "# endif\n"
1176 "}\n"
1177 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1178 "\n"
1179 "#ifdef USESHADOWMAPCUBE\n"
1180 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1181 "{\n"
1182 "    vec3 adir = abs(dir);\n"
1183 "    return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1184 "}\n"
1185 "#endif\n"
1186 "\n"
1187 "# ifdef USESHADOWMAPRECT\n"
1188 "float ShadowMapCompare(vec3 dir)\n"
1189 "{\n"
1190 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1191 "       float f;\n"
1192 "#  ifdef USESHADOWSAMPLER\n"
1193 "\n"
1194 "#    ifdef USESHADOWMAPPCF\n"
1195 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1196 "    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"
1197 "#    else\n"
1198 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1199 "#    endif\n"
1200 "\n"
1201 "#  else\n"
1202 "\n"
1203 "#    ifdef USESHADOWMAPPCF\n"
1204 "#      if USESHADOWMAPPCF > 1\n"
1205 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1206 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1207 "    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"
1208 "    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"
1209 "    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"
1210 "    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"
1211 "    vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1212 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1213 "#      else\n"
1214 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1215 "    vec2 offset = fract(shadowmaptc.xy);\n"
1216 "    vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1217 "    vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1218 "    vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1219 "    vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1220 "    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1221 "#      endif\n"
1222 "#    else\n"
1223 "    f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1224 "#    endif\n"
1225 "\n"
1226 "#  endif\n"
1227 "       return f;\n"
1228 "}\n"
1229 "# endif\n"
1230 "\n"
1231 "# ifdef USESHADOWMAP2D\n"
1232 "float ShadowMapCompare(vec3 dir)\n"
1233 "{\n"
1234 "    vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1235 "    float f;\n"
1236 "\n"
1237 "#  ifdef USESHADOWSAMPLER\n"
1238 "#    ifdef USESHADOWMAPPCF\n"
1239 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1240 "    vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1241 "    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"
1242 "#    else\n"
1243 "    f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1244 "#    endif\n"
1245 "#  else\n"
1246 "#    ifdef USESHADOWMAPPCF\n"
1247 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1248 "#      ifdef GL_ARB_texture_gather\n"
1249 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1250 "#      else\n"
1251 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1252 "#      endif\n"
1253 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1254 "    center *= ShadowMap_TextureScale;\n"
1255 "    vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1256 "    vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1257 "    vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1258 "    vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1259 "    vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1260 "                mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1261 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1262 "#     else\n"
1263 "#      ifdef GL_EXT_gpu_shader4\n"
1264 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1265 "#      else\n"
1266 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1267 "#      endif\n"
1268 "#      if USESHADOWMAPPCF > 1\n"
1269 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1270 "    center *= ShadowMap_TextureScale;\n"
1271 "    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"
1272 "    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"
1273 "    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"
1274 "    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"
1275 "    vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1276 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1277 "#      else\n"
1278 "    vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1279 "    vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1280 "    vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1281 "    vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1282 "    vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1283 "    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1284 "#      endif\n"
1285 "#     endif\n"
1286 "#    else\n"
1287 "    f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1288 "#    endif\n"
1289 "#  endif\n"
1290 "    return f;\n"
1291 "}\n"
1292 "# endif\n"
1293 "\n"
1294 "# ifdef USESHADOWMAPCUBE\n"
1295 "float ShadowMapCompare(vec3 dir)\n"
1296 "{\n"
1297 "    // apply depth texture cubemap as light filter\n"
1298 "    vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1299 "    float f;\n"
1300 "#  ifdef USESHADOWSAMPLER\n"
1301 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1302 "#  else\n"
1303 "    f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1304 "#  endif\n"
1305 "    return f;\n"
1306 "}\n"
1307 "# endif\n"
1308 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1309 "\n"
1310 "#ifdef MODE_DEFERREDGEOMETRY\n"
1311 "void main(void)\n"
1312 "{\n"
1313 "#ifdef USEOFFSETMAPPING\n"
1314 "       // apply offsetmapping\n"
1315 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1316 "#define TexCoord TexCoordOffset\n"
1317 "#endif\n"
1318 "\n"
1319 "#ifdef USEALPHAKILL\n"
1320 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1321 "               discard;\n"
1322 "#endif\n"
1323 "\n"
1324 "#ifdef USEVERTEXTEXTUREBLEND\n"
1325 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1326 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1327 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1328 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1329 "#endif\n"
1330 "\n"
1331 "#ifdef USEVERTEXTEXTUREBLEND\n"
1332 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1333 "#else\n"
1334 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1335 "#endif\n"
1336 "\n"
1337 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1338 "}\n"
1339 "#else // !MODE_DEFERREDGEOMETRY\n"
1340 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1341 "uniform mat4 ViewToLight;\n"
1342 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1343 "uniform vec2 ScreenToDepth;\n"
1344 "uniform myhalf3 DeferredColor_Ambient;\n"
1345 "uniform myhalf3 DeferredColor_Diffuse;\n"
1346 "#ifdef USESPECULAR\n"
1347 "uniform myhalf3 DeferredColor_Specular;\n"
1348 "uniform myhalf SpecularPower;\n"
1349 "#endif\n"
1350 "void main(void)\n"
1351 "{\n"
1352 "       // calculate viewspace pixel position\n"
1353 "       vec3 position;\n"
1354 "       position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1355 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1356 "       // decode viewspace pixel normal\n"
1357 "       myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1358 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1359 "       // surfacenormal = pixel normal in viewspace\n"
1360 "       // LightVector = pixel to light in viewspace\n"
1361 "       // CubeVector = position in lightspace\n"
1362 "       // eyevector = pixel to view in viewspace\n"
1363 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1364 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1365 "#ifdef USEDIFFUSE\n"
1366 "       // calculate diffuse shading\n"
1367 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1368 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1369 "#endif\n"
1370 "#ifdef USESPECULAR\n"
1371 "       // calculate directional shading\n"
1372 "       vec3 eyevector = position * -1.0;\n"
1373 "#  ifdef USEEXACTSPECULARMATH\n"
1374 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1375 "#  else\n"
1376 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1377 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1378 "#  endif\n"
1379 "#endif\n"
1380 "\n"
1381 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1382 "       fade *= ShadowMapCompare(CubeVector);\n"
1383 "#endif\n"
1384 "\n"
1385 "#ifdef USEDIFFUSE\n"
1386 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1387 "#else\n"
1388 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1389 "#endif\n"
1390 "#ifdef USESPECULAR\n"
1391 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1392 "#else\n"
1393 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1394 "#endif\n"
1395 "\n"
1396 "# ifdef USECUBEFILTER\n"
1397 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1398 "       gl_FragData[0] *= cubecolor;\n"
1399 "       gl_FragData[1] *= cubecolor;\n"
1400 "# endif\n"
1401 "}\n"
1402 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1403 "#ifdef USEDEFERREDLIGHTMAP\n"
1404 "uniform myhalf3 DeferredMod_Diffuse;\n"
1405 "uniform myhalf3 DeferredMod_Specular;\n"
1406 "#endif\n"
1407 "uniform myhalf3 Color_Ambient;\n"
1408 "uniform myhalf3 Color_Diffuse;\n"
1409 "uniform myhalf3 Color_Specular;\n"
1410 "uniform myhalf SpecularPower;\n"
1411 "#ifdef USEGLOW\n"
1412 "uniform myhalf3 Color_Glow;\n"
1413 "#endif\n"
1414 "uniform myhalf Alpha;\n"
1415 "#ifdef USEREFLECTION\n"
1416 "uniform vec4 DistortScaleRefractReflect;\n"
1417 "uniform vec4 ScreenScaleRefractReflect;\n"
1418 "uniform vec4 ScreenCenterRefractReflect;\n"
1419 "uniform myhalf4 ReflectColor;\n"
1420 "#endif\n"
1421 "#ifdef MODE_LIGHTDIRECTION\n"
1422 "uniform myhalf3 LightColor;\n"
1423 "#endif\n"
1424 "#ifdef MODE_LIGHTSOURCE\n"
1425 "uniform myhalf3 LightColor;\n"
1426 "#endif\n"
1427 "void main(void)\n"
1428 "{\n"
1429 "#ifdef USEOFFSETMAPPING\n"
1430 "       // apply offsetmapping\n"
1431 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1432 "#define TexCoord TexCoordOffset\n"
1433 "#endif\n"
1434 "\n"
1435 "       // combine the diffuse textures (base, pants, shirt)\n"
1436 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1437 "#ifdef USEALPHAKILL\n"
1438 "       if (color.a < 0.5)\n"
1439 "               discard;\n"
1440 "#endif\n"
1441 "       color.a *= Alpha;\n"
1442 "#ifdef USECOLORMAPPING\n"
1443 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1444 "#endif\n"
1445 "#ifdef USEVERTEXTEXTUREBLEND\n"
1446 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1447 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1448 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1449 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1450 "       color.a = 1.0;\n"
1451 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1452 "#endif\n"
1453 "\n"
1454 "       // get the surface normal\n"
1455 "#ifdef USEVERTEXTEXTUREBLEND\n"
1456 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1457 "#else\n"
1458 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1459 "#endif\n"
1460 "\n"
1461 "       // get the material colors\n"
1462 "       myhalf3 diffusetex = color.rgb;\n"
1463 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1464 "# ifdef USEVERTEXTEXTUREBLEND\n"
1465 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1466 "# else\n"
1467 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1468 "# endif\n"
1469 "#endif\n"
1470 "\n"
1471 "\n"
1472 "\n"
1473 "\n"
1474 "#ifdef MODE_LIGHTSOURCE\n"
1475 "       // light source\n"
1476 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1477 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1478 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1479 "#ifdef USESPECULAR\n"
1480 "#ifdef USEEXACTSPECULARMATH\n"
1481 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1482 "#else\n"
1483 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1484 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1485 "#endif\n"
1486 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1487 "#endif\n"
1488 "       color.rgb *= LightColor;\n"
1489 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1490 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1491 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1492 "#endif\n"
1493 "# ifdef USECUBEFILTER\n"
1494 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1495 "# endif\n"
1496 "#endif // MODE_LIGHTSOURCE\n"
1497 "\n"
1498 "\n"
1499 "\n"
1500 "\n"
1501 "#ifdef MODE_LIGHTDIRECTION\n"
1502 "#define SHADING\n"
1503 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1504 "#define lightcolor LightColor\n"
1505 "#endif // MODE_LIGHTDIRECTION\n"
1506 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1507 "#define SHADING\n"
1508 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1509 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1510 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1511 "       // convert modelspace light vector to tangentspace\n"
1512 "       myhalf3 lightnormal;\n"
1513 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1514 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1515 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1516 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1517 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1518 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1519 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1520 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1521 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1522 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1523 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1524 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1525 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1526 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1527 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1528 "#define SHADING\n"
1529 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1530 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1531 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1532 "#endif\n"
1533 "\n"
1534 "\n"
1535 "\n"
1536 "\n"
1537 "#ifdef MODE_LIGHTMAP\n"
1538 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1539 "#endif // MODE_LIGHTMAP\n"
1540 "#ifdef MODE_VERTEXCOLOR\n"
1541 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1542 "#endif // MODE_VERTEXCOLOR\n"
1543 "#ifdef MODE_FLATCOLOR\n"
1544 "       color.rgb = diffusetex * Color_Ambient;\n"
1545 "#endif // MODE_FLATCOLOR\n"
1546 "\n"
1547 "\n"
1548 "\n"
1549 "\n"
1550 "#ifdef SHADING\n"
1551 "# ifdef USEDIFFUSE\n"
1552 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1553 "#  ifdef USESPECULAR\n"
1554 "#   ifdef USEEXACTSPECULARMATH\n"
1555 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1556 "#   else\n"
1557 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1558 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1559 "#   endif\n"
1560 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1561 "#  else\n"
1562 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1563 "#  endif\n"
1564 "# else\n"
1565 "       color.rgb = diffusetex * Color_Ambient;\n"
1566 "# endif\n"
1567 "#endif\n"
1568 "\n"
1569 "#ifdef USEDEFERREDLIGHTMAP\n"
1570 "       color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1571 "       color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1572 "#endif\n"
1573 "\n"
1574 "#ifdef USEGLOW\n"
1575 "#ifdef USEVERTEXTEXTUREBLEND\n"
1576 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1577 "#else\n"
1578 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1579 "#endif\n"
1580 "#endif\n"
1581 "\n"
1582 "#ifdef USEFOG\n"
1583 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1584 "#endif\n"
1585 "\n"
1586 "       // 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"
1587 "#ifdef USEREFLECTION\n"
1588 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1589 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1590 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1591 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1592 "       // FIXME temporary hack to detect the case that the reflection\n"
1593 "       // gets blackened at edges due to leaving the area that contains actual\n"
1594 "       // content.\n"
1595 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1596 "       // 'appening.\n"
1597 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1598 "       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 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1602 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1603 "#endif\n"
1604 "\n"
1605 "       gl_FragColor = vec4(color);\n"
1606 "}\n"
1607 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1608 "#endif // !MODE_DEFERREDGEOMETRY\n"
1609 "\n"
1610 "#endif // FRAGMENT_SHADER\n"
1611 "\n"
1612 "#endif // !MODE_WATER\n"
1613 "#endif // !MODE_REFRACTION\n"
1614 "#endif // !MODE_BLOOMBLUR\n"
1615 "#endif // !MODE_GENERIC\n"
1616 "#endif // !MODE_POSTPROCESS\n"
1617 "#endif // !MODE_SHOWDEPTH\n"
1618 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1619 ;
1620
1621 const char *builtincgshaderstring = "";
1622
1623 typedef struct shaderpermutationinfo_s
1624 {
1625         const char *pretext;
1626         const char *name;
1627 }
1628 shaderpermutationinfo_t;
1629
1630 typedef struct shadermodeinfo_s
1631 {
1632         const char *vertexfilename;
1633         const char *geometryfilename;
1634         const char *fragmentfilename;
1635         const char *pretext;
1636         const char *name;
1637 }
1638 shadermodeinfo_t;
1639
1640 typedef enum shaderpermutation_e
1641 {
1642         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1643         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1644         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1645         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1646         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1647         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1648         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1649         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1650         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1651         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1652         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1653         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1654         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1655         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1656         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1657         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1658         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1659         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1660         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1661         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1662         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1663         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1664         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1665         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1666         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1667         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
1668         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
1669         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
1670 }
1671 shaderpermutation_t;
1672
1673 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1674 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1675 {
1676         {"#define USEDIFFUSE\n", " diffuse"},
1677         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1678         {"#define USEVIEWTINT\n", " viewtint"},
1679         {"#define USECOLORMAPPING\n", " colormapping"},
1680         {"#define USESATURATION\n", " saturation"},
1681         {"#define USEFOGINSIDE\n", " foginside"},
1682         {"#define USEFOGOUTSIDE\n", " fogoutside"},
1683         {"#define USEGAMMARAMPS\n", " gammaramps"},
1684         {"#define USECUBEFILTER\n", " cubefilter"},
1685         {"#define USEGLOW\n", " glow"},
1686         {"#define USEBLOOM\n", " bloom"},
1687         {"#define USESPECULAR\n", " specular"},
1688         {"#define USEPOSTPROCESSING\n", " postprocessing"},
1689         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1690         {"#define USEREFLECTION\n", " reflection"},
1691         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1692         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1693         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1694         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1695         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1696         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1697         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1698         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1699         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1700         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1701         {"#define USEALPHAKILL\n", " alphakill"},
1702 };
1703
1704 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1705 typedef enum shadermode_e
1706 {
1707         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1708         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1709         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1710         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1711         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1712         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1713         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1714         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1715         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1716         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1717         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1718         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1719         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1720         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1721         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1722         SHADERMODE_COUNT
1723 }
1724 shadermode_t;
1725
1726 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1727 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
1728 {
1729         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1730         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1731         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1732         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1733         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1734         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1735         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1736         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1737         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1738         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1739         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1740         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1741         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1742         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1743         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1744 };
1745
1746 #ifdef SUPPORTCG
1747 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
1748 {
1749         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
1750         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
1751         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1752         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
1753         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1754         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
1755         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1756         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1757         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1758         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1759         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
1760         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
1761         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
1762         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1763         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1764 };
1765 #endif
1766
1767 struct r_glsl_permutation_s;
1768 typedef struct r_glsl_permutation_s
1769 {
1770         /// hash lookup data
1771         struct r_glsl_permutation_s *hashnext;
1772         unsigned int mode;
1773         unsigned int permutation;
1774
1775         /// indicates if we have tried compiling this permutation already
1776         qboolean compiled;
1777         /// 0 if compilation failed
1778         int program;
1779         /// locations of detected uniforms in program object, or -1 if not found
1780         int loc_Texture_First;
1781         int loc_Texture_Second;
1782         int loc_Texture_GammaRamps;
1783         int loc_Texture_Normal;
1784         int loc_Texture_Color;
1785         int loc_Texture_Gloss;
1786         int loc_Texture_Glow;
1787         int loc_Texture_SecondaryNormal;
1788         int loc_Texture_SecondaryColor;
1789         int loc_Texture_SecondaryGloss;
1790         int loc_Texture_SecondaryGlow;
1791         int loc_Texture_Pants;
1792         int loc_Texture_Shirt;
1793         int loc_Texture_FogMask;
1794         int loc_Texture_Lightmap;
1795         int loc_Texture_Deluxemap;
1796         int loc_Texture_Attenuation;
1797         int loc_Texture_Cube;
1798         int loc_Texture_Refraction;
1799         int loc_Texture_Reflection;
1800         int loc_Texture_ShadowMapRect;
1801         int loc_Texture_ShadowMapCube;
1802         int loc_Texture_ShadowMap2D;
1803         int loc_Texture_CubeProjection;
1804         int loc_Texture_ScreenDepth;
1805         int loc_Texture_ScreenNormalMap;
1806         int loc_Texture_ScreenDiffuse;
1807         int loc_Texture_ScreenSpecular;
1808         int loc_Alpha;
1809         int loc_BloomBlur_Parameters;
1810         int loc_ClientTime;
1811         int loc_Color_Ambient;
1812         int loc_Color_Diffuse;
1813         int loc_Color_Specular;
1814         int loc_Color_Glow;
1815         int loc_Color_Pants;
1816         int loc_Color_Shirt;
1817         int loc_DeferredColor_Ambient;
1818         int loc_DeferredColor_Diffuse;
1819         int loc_DeferredColor_Specular;
1820         int loc_DeferredMod_Diffuse;
1821         int loc_DeferredMod_Specular;
1822         int loc_DistortScaleRefractReflect;
1823         int loc_EyePosition;
1824         int loc_FogColor;
1825         int loc_FogHeightFade;
1826         int loc_FogPlane;
1827         int loc_FogPlaneViewDist;
1828         int loc_FogRangeRecip;
1829         int loc_LightColor;
1830         int loc_LightDir;
1831         int loc_LightPosition;
1832         int loc_OffsetMapping_Scale;
1833         int loc_PixelSize;
1834         int loc_ReflectColor;
1835         int loc_ReflectFactor;
1836         int loc_ReflectOffset;
1837         int loc_RefractColor;
1838         int loc_Saturation;
1839         int loc_ScreenCenterRefractReflect;
1840         int loc_ScreenScaleRefractReflect;
1841         int loc_ScreenToDepth;
1842         int loc_ShadowMap_Parameters;
1843         int loc_ShadowMap_TextureScale;
1844         int loc_SpecularPower;
1845         int loc_UserVec1;
1846         int loc_UserVec2;
1847         int loc_UserVec3;
1848         int loc_UserVec4;
1849         int loc_ViewTintColor;
1850         int loc_ViewToLight;
1851         int loc_ModelToLight;
1852         int loc_TexMatrix;
1853         int loc_BackgroundTexMatrix;
1854         int loc_ModelViewProjectionMatrix;
1855         int loc_ModelViewMatrix;
1856 }
1857 r_glsl_permutation_t;
1858
1859 #define SHADERPERMUTATION_HASHSIZE 256
1860
1861 /// information about each possible shader permutation
1862 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1863 /// currently selected permutation
1864 r_glsl_permutation_t *r_glsl_permutation;
1865 /// storage for permutations linked in the hash table
1866 memexpandablearray_t r_glsl_permutationarray;
1867
1868 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1869 {
1870         //unsigned int hashdepth = 0;
1871         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1872         r_glsl_permutation_t *p;
1873         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1874         {
1875                 if (p->mode == mode && p->permutation == permutation)
1876                 {
1877                         //if (hashdepth > 10)
1878                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1879                         return p;
1880                 }
1881                 //hashdepth++;
1882         }
1883         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1884         p->mode = mode;
1885         p->permutation = permutation;
1886         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1887         r_glsl_permutationhash[mode][hashindex] = p;
1888         //if (hashdepth > 10)
1889         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1890         return p;
1891 }
1892
1893 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1894 {
1895         char *shaderstring;
1896         if (!filename || !filename[0])
1897                 return NULL;
1898         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1899         if (shaderstring)
1900         {
1901                 if (printfromdisknotice)
1902                         Con_DPrintf("from disk %s... ", filename);
1903                 return shaderstring;
1904         }
1905         else if (!strcmp(filename, "glsl/default.glsl"))
1906         {
1907                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1908                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1909         }
1910         return shaderstring;
1911 }
1912
1913 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1914 {
1915         int i;
1916         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1917         int vertstrings_count = 0;
1918         int geomstrings_count = 0;
1919         int fragstrings_count = 0;
1920         char *vertexstring, *geometrystring, *fragmentstring;
1921         const char *vertstrings_list[32+3];
1922         const char *geomstrings_list[32+3];
1923         const char *fragstrings_list[32+3];
1924         char permutationname[256];
1925
1926         if (p->compiled)
1927                 return;
1928         p->compiled = true;
1929         p->program = 0;
1930
1931         permutationname[0] = 0;
1932         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1933         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1934         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1935
1936         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1937
1938         // the first pretext is which type of shader to compile as
1939         // (later these will all be bound together as a program object)
1940         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1941         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1942         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1943
1944         // the second pretext is the mode (for example a light source)
1945         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1946         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1947         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1948         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1949
1950         // now add all the permutation pretexts
1951         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1952         {
1953                 if (permutation & (1<<i))
1954                 {
1955                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1956                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1957                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1958                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1959                 }
1960                 else
1961                 {
1962                         // keep line numbers correct
1963                         vertstrings_list[vertstrings_count++] = "\n";
1964                         geomstrings_list[geomstrings_count++] = "\n";
1965                         fragstrings_list[fragstrings_count++] = "\n";
1966                 }
1967         }
1968
1969         // now append the shader text itself
1970         vertstrings_list[vertstrings_count++] = vertexstring;
1971         geomstrings_list[geomstrings_count++] = geometrystring;
1972         fragstrings_list[fragstrings_count++] = fragmentstring;
1973
1974         // if any sources were NULL, clear the respective list
1975         if (!vertexstring)
1976                 vertstrings_count = 0;
1977         if (!geometrystring)
1978                 geomstrings_count = 0;
1979         if (!fragmentstring)
1980                 fragstrings_count = 0;
1981
1982         // compile the shader program
1983         if (vertstrings_count + geomstrings_count + fragstrings_count)
1984                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1985         if (p->program)
1986         {
1987                 CHECKGLERROR
1988                 qglUseProgramObjectARB(p->program);CHECKGLERROR
1989                 // look up all the uniform variable names we care about, so we don't
1990                 // have to look them up every time we set them
1991
1992                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
1993                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
1994                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1995                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
1996                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
1997                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1998                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
1999                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
2000                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
2001                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
2002                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
2003                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
2004                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
2005                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
2006                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
2007                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
2008                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
2009                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
2010                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
2011                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
2012                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
2013                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
2014                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
2015                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
2016                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
2017                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
2018                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
2019                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
2020                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
2021                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
2022                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
2023                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
2024                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
2025                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
2026                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
2027                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
2028                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
2029                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
2030                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
2031                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
2032                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
2033                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
2034                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
2035                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
2036                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
2037                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
2038                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
2039                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
2040                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
2041                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
2042                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
2043                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
2044                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
2045                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
2046                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
2047                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
2048                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
2049                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
2050                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
2051                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
2052                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2053                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2054                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2055                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2056                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
2057                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
2058                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
2059                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
2060                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
2061                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
2062                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
2063                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
2064                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
2065                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
2066                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
2067                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
2068                 // initialize the samplers to refer to the texture units we use
2069                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
2070                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
2071                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
2072                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
2073                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
2074                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
2075                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
2076                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2077                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2078                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2079                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
2080                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
2081                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
2082                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
2083                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
2084                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
2085                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
2086                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
2087                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
2088                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
2089                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
2090                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
2091                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
2092                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2093                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
2094                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2095                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
2096                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2097                 CHECKGLERROR
2098                 if (developer.integer)
2099                         Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2100         }
2101         else
2102                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
2103
2104         // free the strings
2105         if (vertexstring)
2106                 Mem_Free(vertexstring);
2107         if (geometrystring)
2108                 Mem_Free(geometrystring);
2109         if (fragmentstring)
2110                 Mem_Free(fragmentstring);
2111 }
2112
2113 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
2114 {
2115         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2116         if (r_glsl_permutation != perm)
2117         {
2118                 r_glsl_permutation = perm;
2119                 if (!r_glsl_permutation->program)
2120                 {
2121                         if (!r_glsl_permutation->compiled)
2122                                 R_GLSL_CompilePermutation(perm, mode, permutation);
2123                         if (!r_glsl_permutation->program)
2124                         {
2125                                 // remove features until we find a valid permutation
2126                                 int i;
2127                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2128                                 {
2129                                         // reduce i more quickly whenever it would not remove any bits
2130                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2131                                         if (!(permutation & j))
2132                                                 continue;
2133                                         permutation -= j;
2134                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2135                                         if (!r_glsl_permutation->compiled)
2136                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
2137                                         if (r_glsl_permutation->program)
2138                                                 break;
2139                                 }
2140                                 if (i >= SHADERPERMUTATION_COUNT)
2141                                 {
2142                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2143                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2144                                         qglUseProgramObjectARB(0);CHECKGLERROR
2145                                         return; // no bit left to clear, entire mode is broken
2146                                 }
2147                         }
2148                 }
2149                 CHECKGLERROR
2150                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2151         }
2152         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
2153 }
2154
2155 #ifdef SUPPORTCG
2156 #include <Cg/cgGL.h>
2157 struct r_cg_permutation_s;
2158 typedef struct r_cg_permutation_s
2159 {
2160         /// hash lookup data
2161         struct r_cg_permutation_s *hashnext;
2162         unsigned int mode;
2163         unsigned int permutation;
2164
2165         /// indicates if we have tried compiling this permutation already
2166         qboolean compiled;
2167         /// 0 if compilation failed
2168         CGprogram vprogram;
2169         CGprogram fprogram;
2170         /// locations of detected parameters in programs, or NULL if not found
2171         CGparameter vp_EyePosition;
2172         CGparameter vp_FogPlane;
2173         CGparameter vp_LightDir;
2174         CGparameter vp_LightPosition;
2175         CGparameter vp_ModelToLight;
2176         CGparameter vp_TexMatrix;
2177         CGparameter vp_BackgroundTexMatrix;
2178         CGparameter vp_ModelViewProjectionMatrix;
2179         CGparameter vp_ModelViewMatrix;
2180
2181         CGparameter fp_Texture_First;
2182         CGparameter fp_Texture_Second;
2183         CGparameter fp_Texture_GammaRamps;
2184         CGparameter fp_Texture_Normal;
2185         CGparameter fp_Texture_Color;
2186         CGparameter fp_Texture_Gloss;
2187         CGparameter fp_Texture_Glow;
2188         CGparameter fp_Texture_SecondaryNormal;
2189         CGparameter fp_Texture_SecondaryColor;
2190         CGparameter fp_Texture_SecondaryGloss;
2191         CGparameter fp_Texture_SecondaryGlow;
2192         CGparameter fp_Texture_Pants;
2193         CGparameter fp_Texture_Shirt;
2194         CGparameter fp_Texture_FogMask;
2195         CGparameter fp_Texture_Lightmap;
2196         CGparameter fp_Texture_Deluxemap;
2197         CGparameter fp_Texture_Attenuation;
2198         CGparameter fp_Texture_Cube;
2199         CGparameter fp_Texture_Refraction;
2200         CGparameter fp_Texture_Reflection;
2201         CGparameter fp_Texture_ShadowMapRect;
2202         CGparameter fp_Texture_ShadowMapCube;
2203         CGparameter fp_Texture_ShadowMap2D;
2204         CGparameter fp_Texture_CubeProjection;
2205         CGparameter fp_Texture_ScreenDepth;
2206         CGparameter fp_Texture_ScreenNormalMap;
2207         CGparameter fp_Texture_ScreenDiffuse;
2208         CGparameter fp_Texture_ScreenSpecular;
2209         CGparameter fp_Alpha;
2210         CGparameter fp_BloomBlur_Parameters;
2211         CGparameter fp_ClientTime;
2212         CGparameter fp_Color_Ambient;
2213         CGparameter fp_Color_Diffuse;
2214         CGparameter fp_Color_Specular;
2215         CGparameter fp_Color_Glow;
2216         CGparameter fp_Color_Pants;
2217         CGparameter fp_Color_Shirt;
2218         CGparameter fp_DeferredColor_Ambient;
2219         CGparameter fp_DeferredColor_Diffuse;
2220         CGparameter fp_DeferredColor_Specular;
2221         CGparameter fp_DeferredMod_Diffuse;
2222         CGparameter fp_DeferredMod_Specular;
2223         CGparameter fp_DistortScaleRefractReflect;
2224         CGparameter fp_EyePosition;
2225         CGparameter fp_FogColor;
2226         CGparameter fp_FogHeightFade;
2227         CGparameter fp_FogPlane;
2228         CGparameter fp_FogPlaneViewDist;
2229         CGparameter fp_FogRangeRecip;
2230         CGparameter fp_LightColor;
2231         CGparameter fp_LightDir;
2232         CGparameter fp_LightPosition;
2233         CGparameter fp_OffsetMapping_Scale;
2234         CGparameter fp_PixelSize;
2235         CGparameter fp_ReflectColor;
2236         CGparameter fp_ReflectFactor;
2237         CGparameter fp_ReflectOffset;
2238         CGparameter fp_RefractColor;
2239         CGparameter fp_Saturation;
2240         CGparameter fp_ScreenCenterRefractReflect;
2241         CGparameter fp_ScreenScaleRefractReflect;
2242         CGparameter fp_ScreenToDepth;
2243         CGparameter fp_ShadowMap_Parameters;
2244         CGparameter fp_ShadowMap_TextureScale;
2245         CGparameter fp_SpecularPower;
2246         CGparameter fp_UserVec1;
2247         CGparameter fp_UserVec2;
2248         CGparameter fp_UserVec3;
2249         CGparameter fp_UserVec4;
2250         CGparameter fp_ViewTintColor;
2251         CGparameter fp_ViewToLight;
2252 }
2253 r_cg_permutation_t;
2254
2255 /// information about each possible shader permutation
2256 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
2257 /// currently selected permutation
2258 r_cg_permutation_t *r_cg_permutation;
2259 /// storage for permutations linked in the hash table
2260 memexpandablearray_t r_cg_permutationarray;
2261
2262 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
2263 {
2264         //unsigned int hashdepth = 0;
2265         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
2266         r_cg_permutation_t *p;
2267         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
2268         {
2269                 if (p->mode == mode && p->permutation == permutation)
2270                 {
2271                         //if (hashdepth > 10)
2272                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
2273                         return p;
2274                 }
2275                 //hashdepth++;
2276         }
2277         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
2278         p->mode = mode;
2279         p->permutation = permutation;
2280         p->hashnext = r_cg_permutationhash[mode][hashindex];
2281         r_cg_permutationhash[mode][hashindex] = p;
2282         //if (hashdepth > 10)
2283         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
2284         return p;
2285 }
2286
2287 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
2288 {
2289         char *shaderstring;
2290         if (!filename || !filename[0])
2291                 return NULL;
2292         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
2293         if (shaderstring)
2294         {
2295                 if (printfromdisknotice)
2296                         Con_DPrintf("from disk %s... ", filename);
2297                 return shaderstring;
2298         }
2299         else if (!strcmp(filename, "cg/default.cg"))
2300         {
2301                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
2302                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
2303         }
2304         return shaderstring;
2305 }
2306
2307 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
2308 {
2309         int i;
2310         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
2311         int vertstrings_count = 0, vertstring_length = 0;
2312         int geomstrings_count = 0, geomstring_length = 0;
2313         int fragstrings_count = 0, fragstring_length = 0;
2314         char *t;
2315         char *vertexstring, *geometrystring, *fragmentstring;
2316         char *vertstring, *geomstring, *fragstring;
2317         const char *vertstrings_list[32+3];
2318         const char *geomstrings_list[32+3];
2319         const char *fragstrings_list[32+3];
2320         char permutationname[256];
2321
2322         if (p->compiled)
2323                 return;
2324         p->compiled = true;
2325         p->vprogram = NULL;
2326         p->fprogram = NULL;
2327
2328         permutationname[0] = 0;
2329         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
2330         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
2331         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
2332
2333         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
2334
2335         // the first pretext is which type of shader to compile as
2336         // (later these will all be bound together as a program object)
2337         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
2338         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
2339         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
2340
2341         // the second pretext is the mode (for example a light source)
2342         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
2343         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
2344         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
2345         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
2346
2347         // now add all the permutation pretexts
2348         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2349         {
2350                 if (permutation & (1<<i))
2351                 {
2352                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
2353                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
2354                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
2355                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
2356                 }
2357                 else
2358                 {
2359                         // keep line numbers correct
2360                         vertstrings_list[vertstrings_count++] = "\n";
2361                         geomstrings_list[geomstrings_count++] = "\n";
2362                         fragstrings_list[fragstrings_count++] = "\n";
2363                 }
2364         }
2365
2366         // now append the shader text itself
2367         vertstrings_list[vertstrings_count++] = vertexstring;
2368         geomstrings_list[geomstrings_count++] = geometrystring;
2369         fragstrings_list[fragstrings_count++] = fragmentstring;
2370
2371         // if any sources were NULL, clear the respective list
2372         if (!vertexstring)
2373                 vertstrings_count = 0;
2374         if (!geometrystring)
2375                 geomstrings_count = 0;
2376         if (!fragmentstring)
2377                 fragstrings_count = 0;
2378
2379         vertstring_length = 0;
2380         for (i = 0;i < vertstrings_count;i++)
2381                 vertstring_length += strlen(vertstrings_list[i]);
2382         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
2383         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
2384                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
2385
2386         geomstring_length = 0;
2387         for (i = 0;i < geomstrings_count;i++)
2388                 geomstring_length += strlen(geomstrings_list[i]);
2389         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
2390         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
2391                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
2392
2393         fragstring_length = 0;
2394         for (i = 0;i < fragstrings_count;i++)
2395                 fragstring_length += strlen(fragstrings_list[i]);
2396         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
2397         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
2398                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
2399
2400         // compile the shader program
2401         if (vertstring[0] || geomstring[0] || fragstring[0])
2402         {
2403                 if (vertstring[0])
2404                         p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL);
2405                 if (fragstring[0])
2406                         p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL);
2407         }
2408
2409         if (p->vprogram)
2410         {
2411                 cgGLBindProgram(p->vprogram);
2412                 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2413         }
2414         else
2415                 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2416         if (p->fprogram)
2417         {
2418                 cgGLBindProgram(p->fprogram);
2419                 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2420         }
2421         else
2422                 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2423
2424         if (p->vprogram || p->fprogram)
2425         {
2426                 // look up all the uniform variable names we care about, so we don't
2427                 // have to look them up every time we set them
2428                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
2429                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
2430                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
2431                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
2432                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
2433                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
2434                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
2435                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
2436                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
2437
2438                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
2439                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
2440                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
2441                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
2442                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
2443                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
2444                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
2445                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
2446                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
2447                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
2448                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
2449                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
2450                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
2451                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
2452                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
2453                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
2454                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
2455                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
2456                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
2457                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
2458                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
2459                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
2460                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
2461                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
2462                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
2463                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
2464                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
2465                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
2466                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
2467                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
2468                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
2469                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
2470                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
2471                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
2472                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
2473                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
2474                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
2475                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
2476                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
2477                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
2478                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
2479                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
2480                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
2481                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
2482                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
2483                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
2484                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
2485                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
2486                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
2487                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
2488                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
2489                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
2490                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
2491                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
2492                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
2493                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
2494                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
2495                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
2496                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
2497                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
2498                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
2499                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
2500                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
2501                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
2502                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
2503                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
2504                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
2505                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
2506                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
2507                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
2508                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
2509                 CHECKGLERROR
2510                 if (developer.integer)
2511                         Con_Printf("^5CG shader %s compiled.\n", permutationname);
2512         }
2513         else
2514                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
2515
2516         // free the strings
2517         if (vertstring)
2518                 Mem_Free(vertstring);
2519         if (geomstring)
2520                 Mem_Free(geomstring);
2521         if (fragstring)
2522                 Mem_Free(fragstring);
2523         if (vertexstring)
2524                 Mem_Free(vertexstring);
2525         if (geometrystring)
2526                 Mem_Free(geometrystring);
2527         if (fragmentstring)
2528                 Mem_Free(fragmentstring);
2529 }
2530
2531 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
2532 {
2533         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
2534         if (r_cg_permutation != perm)
2535         {
2536                 r_cg_permutation = perm;
2537                 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));
2538                 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2539                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
2540                 {
2541                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2542                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2543                         if (!r_cg_permutation->compiled)
2544                                 R_CG_CompilePermutation(perm, mode, permutation);
2545                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
2546                         {
2547                                 // remove features until we find a valid permutation
2548                                 int i;
2549                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2550                                 {
2551                                         // reduce i more quickly whenever it would not remove any bits
2552                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2553                                         if (!(permutation & j))
2554                                                 continue;
2555                                         permutation -= j;
2556                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
2557                                         if (!r_cg_permutation->compiled)
2558                                                 R_CG_CompilePermutation(perm, mode, permutation);
2559                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
2560                                                 break;
2561                                 }
2562                                 if (i >= SHADERPERMUTATION_COUNT)
2563                                 {
2564                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2565                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
2566                                         return; // no bit left to clear, entire mode is broken
2567                                 }
2568                         }
2569                 }
2570                 CHECKGLERROR
2571                 if (r_cg_permutation->vprogram)
2572                 {
2573                         cgGLBindProgram(r_cg_permutation->vprogram);
2574                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2575                 }
2576                 else
2577                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2578                 if (r_cg_permutation->fprogram)
2579                 {
2580                         cgGLBindProgram(r_cg_permutation->fprogram);
2581                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2582                 }
2583                 else
2584                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2585         }
2586         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);
2587 }
2588 #endif
2589
2590 void R_GLSL_Restart_f(void)
2591 {
2592         unsigned int i, limit;
2593         r_glsl_permutation_t *p;
2594         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2595         for (i = 0;i < limit;i++)
2596         {
2597                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2598                 {
2599                         GL_Backend_FreeProgram(p->program);
2600                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2601                 }
2602         }
2603         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2604 #ifdef SUPPORTCG
2605         if (vid.cgcontext)
2606         {
2607                 r_cg_permutation_t *p;
2608                 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
2609                 for (i = 0;i < limit;i++)
2610                 {
2611                         if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
2612                         {
2613                                 if (p->vprogram)
2614                                         cgDestroyProgram(p->vprogram);
2615                                 if (p->fprogram)
2616                                         cgDestroyProgram(p->fprogram);
2617                                 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
2618                         }
2619                 }
2620                 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
2621         }
2622 #endif
2623 }
2624
2625 void R_GLSL_DumpShader_f(void)
2626 {
2627         int i;
2628         qfile_t *file;
2629
2630         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2631         if (file)
2632         {
2633                 FS_Print(file, "/* The engine may define the following macros:\n");
2634                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2635                 for (i = 0;i < SHADERMODE_COUNT;i++)
2636                         FS_Print(file, glslshadermodeinfo[i].pretext);
2637                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2638                         FS_Print(file, shaderpermutationinfo[i].pretext);
2639                 FS_Print(file, "*/\n");
2640                 FS_Print(file, builtinshaderstring);
2641                 FS_Close(file);
2642                 Con_Printf("glsl/default.glsl written\n");
2643         }
2644         else
2645                 Con_Printf("failed to write to glsl/default.glsl\n");
2646
2647 #ifdef SUPPORTCG
2648         file = FS_OpenRealFile("cg/default.cg", "w", false);
2649         if (file)
2650         {
2651                 FS_Print(file, "/* The engine may define the following macros:\n");
2652                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2653                 for (i = 0;i < SHADERMODE_COUNT;i++)
2654                         FS_Print(file, cgshadermodeinfo[i].pretext);
2655                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2656                         FS_Print(file, shaderpermutationinfo[i].pretext);
2657                 FS_Print(file, "*/\n");
2658                 FS_Print(file, builtincgshaderstring);
2659                 FS_Close(file);
2660                 Con_Printf("cg/default.cg written\n");
2661         }
2662         else
2663                 Con_Printf("failed to write to cg/default.cg\n");
2664 #endif
2665 }
2666
2667 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
2668 {
2669         if (!second)
2670                 texturemode = GL_MODULATE;
2671         switch (vid.renderpath)
2672         {
2673         case RENDERPATH_GL20:
2674                 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))));
2675                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(first ));
2676                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, R_GetTexture(second));
2677                 break;
2678         case RENDERPATH_CGGL:
2679 #ifdef SUPPORTCG
2680                 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))));
2681                 if (r_cg_permutation->fp_Texture_First ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First , R_GetTexture(first ));
2682                 if (r_cg_permutation->fp_Texture_Second) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second, R_GetTexture(second));
2683 #endif
2684                 break;
2685         case RENDERPATH_GL13:
2686                 R_Mesh_TexBind(0, R_GetTexture(first ));
2687                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2688                 R_Mesh_TexBind(1, R_GetTexture(second));
2689                 if (second)
2690                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2691                 break;
2692         case RENDERPATH_GL11:
2693                 R_Mesh_TexBind(0, R_GetTexture(first ));
2694                 break;
2695         }
2696 }
2697
2698 void R_SetupShader_DepthOrShadow(void)
2699 {
2700         switch (vid.renderpath)
2701         {
2702         case RENDERPATH_GL20:
2703                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
2704                 break;
2705         case RENDERPATH_CGGL:
2706 #ifdef SUPPORTCG
2707                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
2708 #endif
2709                 break;
2710         case RENDERPATH_GL13:
2711                 R_Mesh_TexBind(0, 0);
2712                 R_Mesh_TexBind(1, 0);
2713                 break;
2714         case RENDERPATH_GL11:
2715                 R_Mesh_TexBind(0, 0);
2716                 break;
2717         }
2718 }
2719
2720 void R_SetupShader_ShowDepth(void)
2721 {
2722         switch (vid.renderpath)
2723         {
2724         case RENDERPATH_GL20:
2725                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
2726                 break;
2727         case RENDERPATH_CGGL:
2728 #ifdef SUPPORTCG
2729                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
2730 #endif
2731                 break;
2732         case RENDERPATH_GL13:
2733                 break;
2734         case RENDERPATH_GL11:
2735                 break;
2736         }
2737 }
2738
2739 extern qboolean r_shadow_usingdeferredprepass;
2740 extern cvar_t r_shadow_deferred_8bitrange;
2741 extern rtexture_t *r_shadow_attenuationgradienttexture;
2742 extern rtexture_t *r_shadow_attenuation2dtexture;
2743 extern rtexture_t *r_shadow_attenuation3dtexture;
2744 extern qboolean r_shadow_usingshadowmaprect;
2745 extern qboolean r_shadow_usingshadowmapcube;
2746 extern qboolean r_shadow_usingshadowmap2d;
2747 extern float r_shadow_shadowmap_texturescale[2];
2748 extern float r_shadow_shadowmap_parameters[4];
2749 extern qboolean r_shadow_shadowmapvsdct;
2750 extern qboolean r_shadow_shadowmapsampler;
2751 extern int r_shadow_shadowmappcf;
2752 extern rtexture_t *r_shadow_shadowmaprectangletexture;
2753 extern rtexture_t *r_shadow_shadowmap2dtexture;
2754 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
2755 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2756 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2757 extern int r_shadow_prepass_width;
2758 extern int r_shadow_prepass_height;
2759 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2760 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2761 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2762 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2763 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2764 {
2765         // select a permutation of the lighting shader appropriate to this
2766         // combination of texture, entity, light source, and fogging, only use the
2767         // minimum features necessary to avoid wasting rendering time in the
2768         // fragment shader on features that are not being used
2769         unsigned int permutation = 0;
2770         unsigned int mode = 0;
2771         float m16f[16];
2772         // TODO: implement geometry-shader based shadow volumes someday
2773         if (r_glsl_offsetmapping.integer)
2774         {
2775                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2776                 if (r_glsl_offsetmapping_reliefmapping.integer)
2777                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2778         }
2779         if (rsurfacepass == RSURFPASS_BACKGROUND)
2780         {
2781                 // distorted background
2782                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2783                         mode = SHADERMODE_WATER;
2784                 else
2785                         mode = SHADERMODE_REFRACTION;
2786         }
2787         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2788         {
2789                 // normalmap (deferred prepass), may use alpha test on diffuse
2790                 mode = SHADERMODE_DEFERREDGEOMETRY;
2791                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2792                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2793                 if (r_glsl_offsetmapping.integer)
2794                 {
2795                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2796                         if (r_glsl_offsetmapping_reliefmapping.integer)
2797                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2798                 }
2799         }
2800         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2801         {
2802                 // light source
2803                 mode = SHADERMODE_LIGHTSOURCE;
2804                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2805                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2806                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2807                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2808                 if (diffusescale > 0)
2809                         permutation |= SHADERPERMUTATION_DIFFUSE;
2810                 if (specularscale > 0)
2811                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2812                 if (r_refdef.fogenabled)
2813                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2814                 if (rsurface.texture->colormapping)
2815                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2816                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2817                 {
2818                         if (r_shadow_usingshadowmaprect)
2819                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2820                         if (r_shadow_usingshadowmap2d)
2821                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2822                         if (r_shadow_usingshadowmapcube)
2823                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2824                         else if(r_shadow_shadowmapvsdct)
2825                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2826
2827                         if (r_shadow_shadowmapsampler)
2828                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2829                         if (r_shadow_shadowmappcf > 1)
2830                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2831                         else if (r_shadow_shadowmappcf)
2832                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2833                 }
2834         }
2835         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2836         {
2837                 // unshaded geometry (fullbright or ambient model lighting)
2838                 mode = SHADERMODE_FLATCOLOR;
2839                 ambientscale = diffusescale = specularscale = 0;
2840                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2841                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2842                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2843                         permutation |= SHADERPERMUTATION_GLOW;
2844                 if (r_refdef.fogenabled)
2845                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2846                 if (rsurface.texture->colormapping)
2847                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2848                 if (r_glsl_offsetmapping.integer)
2849                 {
2850                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2851                         if (r_glsl_offsetmapping_reliefmapping.integer)
2852                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2853                 }
2854                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2855                         permutation |= SHADERPERMUTATION_REFLECTION;
2856         }
2857         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2858         {
2859                 // directional model lighting
2860                 mode = SHADERMODE_LIGHTDIRECTION;
2861                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2862                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2863                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2864                         permutation |= SHADERPERMUTATION_GLOW;
2865                 permutation |= SHADERPERMUTATION_DIFFUSE;
2866                 if (specularscale > 0)
2867                         permutation |= SHADERPERMUTATION_SPECULAR;
2868                 if (r_refdef.fogenabled)
2869                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2870                 if (rsurface.texture->colormapping)
2871                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2872                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2873                         permutation |= SHADERPERMUTATION_REFLECTION;
2874                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2875                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2876         }
2877         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2878         {
2879                 // ambient model lighting
2880                 mode = SHADERMODE_LIGHTDIRECTION;
2881                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2882                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2883                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2884                         permutation |= SHADERPERMUTATION_GLOW;
2885                 if (r_refdef.fogenabled)
2886                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2887                 if (rsurface.texture->colormapping)
2888                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2889                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2890                         permutation |= SHADERPERMUTATION_REFLECTION;
2891                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2892                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2893         }
2894         else
2895         {
2896                 // lightmapped wall
2897                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2898                 {
2899                         // deluxemapping (light direction texture)
2900                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2901                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2902                         else
2903                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2904                         permutation |= SHADERPERMUTATION_DIFFUSE;
2905                         if (specularscale > 0)
2906                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2907                 }
2908                 else if (r_glsl_deluxemapping.integer >= 2)
2909                 {
2910                         // fake deluxemapping (uniform light direction in tangentspace)
2911                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2912                         permutation |= SHADERPERMUTATION_DIFFUSE;
2913                         if (specularscale > 0)
2914                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2915                 }
2916                 else if (rsurface.uselightmaptexture)
2917                 {
2918                         // ordinary lightmapping (q1bsp, q3bsp)
2919                         mode = SHADERMODE_LIGHTMAP;
2920                 }
2921                 else
2922                 {
2923                         // ordinary vertex coloring (q3bsp)
2924                         mode = SHADERMODE_VERTEXCOLOR;
2925                 }
2926                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2927                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2928                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2929                         permutation |= SHADERPERMUTATION_GLOW;
2930                 if (r_refdef.fogenabled)
2931                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2932                 if (rsurface.texture->colormapping)
2933                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2934                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2935                         permutation |= SHADERPERMUTATION_REFLECTION;
2936                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2937                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2938         }
2939         if(permutation & SHADERPERMUTATION_SPECULAR)
2940                 if(r_shadow_glossexact.integer)
2941                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2942         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
2943                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2944         switch(vid.renderpath)
2945         {
2946         case RENDERPATH_GL20:
2947                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2948                 if (mode == SHADERMODE_LIGHTSOURCE)
2949                 {
2950                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2951                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2952                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2953                         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);
2954                         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);
2955                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
2956         
2957                         // additive passes are only darkened by fog, not tinted
2958                         if (r_glsl_permutation->loc_FogColor >= 0)
2959                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2960                         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]);
2961                         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]);
2962                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2963                 }
2964                 else
2965                 {
2966                         if (mode == SHADERMODE_FLATCOLOR)
2967                         {
2968                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
2969                         }
2970                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2971                         {
2972                                 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]);
2973                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
2974                                 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);
2975                                 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);
2976                                 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);
2977                                 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]);
2978                                 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]);
2979                         }
2980                         else
2981                         {
2982                                 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]);
2983                                 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]);
2984                                 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);
2985                                 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);
2986                                 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);
2987                         }
2988                         // additive passes are only darkened by fog, not tinted
2989                         if (r_glsl_permutation->loc_FogColor >= 0)
2990                         {
2991                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2992                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2993                                 else
2994                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2995                         }
2996                         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);
2997                         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]);
2998                         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]);
2999                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
3000                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
3001                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3002                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
3003                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3004                 }
3005                 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3006                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
3007                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
3008                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3009                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
3010                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3011                 if (r_glsl_permutation->loc_Color_Pants >= 0)
3012                 {
3013                         if (rsurface.texture->pantstexture)
3014                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3015                         else
3016                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
3017                 }
3018                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
3019                 {
3020                         if (rsurface.texture->shirttexture)
3021                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3022                         else
3023                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
3024                 }
3025                 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]);
3026                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
3027                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
3028                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
3029                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
3030                 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]);
3031
3032         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             ,          R_GetTexture(r_texture_white                                     ));
3033         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            ,          R_GetTexture(r_texture_white                                     ));
3034         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        ,          R_GetTexture(r_texture_gammaramps                                ));
3035                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            ,          R_GetTexture(rsurface.texture->nmaptexture                       ));
3036                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             ,          R_GetTexture(rsurface.texture->basetexture                       ));
3037                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             ,          R_GetTexture(rsurface.texture->glosstexture                      ));
3038                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              ,          R_GetTexture(rsurface.texture->glowtexture                       ));
3039                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  ,          R_GetTexture(rsurface.texture->backgroundnmaptexture             ));
3040                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   ,          R_GetTexture(rsurface.texture->backgroundbasetexture             ));
3041                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   ,          R_GetTexture(rsurface.texture->backgroundglosstexture            ));
3042                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    ,          R_GetTexture(rsurface.texture->backgroundglowtexture             ));
3043                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             ,          R_GetTexture(rsurface.texture->pantstexture                      ));
3044                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             ,          R_GetTexture(rsurface.texture->shirttexture                      ));
3045                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           ,          R_GetTexture(r_texture_fogattenuation                            ));
3046                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          ,          R_GetTexture(r_texture_white                                     ));
3047                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          ,          R_GetTexture(r_texture_blanknormalmap                            ));
3048                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       ,          R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3049                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        ,          R_GetTexture(r_texture_white                                     ));
3050                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        ,          R_GetTexture(r_texture_white                                     ));
3051                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH    , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3052                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3053                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE  , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture              ));
3054                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture             ));
3055                 if (rsurface.rtlight)
3056                 {
3057                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBindAll(GL20TU_CUBE           , 0, 0,    R_GetTexture(rsurface.rtlight->currentcubemap                    ), 0);
3058                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT  , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3059                         if (r_shadow_usingshadowmapcube)
3060                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE  , 0, 0,    R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
3061                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       ,          R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3062                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0,    R_GetTexture(r_shadow_shadowmapvsdcttexture                      ), 0);
3063                 }
3064                 CHECKGLERROR
3065                 break;
3066         case RENDERPATH_CGGL:
3067 #ifdef SUPPORTCG
3068                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3069                 if (mode == SHADERMODE_LIGHTSOURCE)
3070                 {
3071                         if (r_cg_permutation->vp_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}
3072                         if (r_cg_permutation->vp_LightPosition >= 0) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
3073                 }
3074                 else
3075                 {
3076                         if (mode == SHADERMODE_LIGHTDIRECTION)
3077                         {
3078                                 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]);
3079                         }
3080                 }
3081                 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);
3082                 if (r_cg_permutation->vp_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}
3083                 if (r_cg_permutation->vp_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}
3084                 if (r_cg_permutation->vp_EyePosition >= 0) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3085                 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]);
3086                 CHECKGLERROR
3087
3088                 if (mode == SHADERMODE_LIGHTSOURCE)
3089                 {
3090                         if (r_cg_permutation->fp_LightPosition >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
3091                         if (r_cg_permutation->fp_LightColor >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
3092                         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);
3093                         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);
3094                         if (r_cg_permutation->fp_Color_Specular >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);
3095
3096                         // additive passes are only darkened by fog, not tinted
3097                         if (r_cg_permutation->fp_FogColor >= 0)
3098                                 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
3099                         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]);
3100                         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]);
3101                         if (r_cg_permutation->fp_SpecularPower >= 0) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3102                 }
3103                 else
3104                 {
3105                         if (mode == SHADERMODE_FLATCOLOR)
3106                         {
3107                                 if (r_cg_permutation->fp_Color_Ambient >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
3108                         }
3109                         else if (mode == SHADERMODE_LIGHTDIRECTION)
3110                         {
3111                                 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]);
3112                                 if (r_cg_permutation->fp_Color_Diffuse >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
3113                                 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);
3114                                 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);
3115                                 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);
3116                                 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]);
3117                                 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]);
3118                         }
3119                         else
3120                         {
3121                                 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]);
3122                                 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]);
3123                                 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);
3124                                 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);
3125                                 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);
3126                         }
3127                         // additive passes are only darkened by fog, not tinted
3128                         if (r_cg_permutation->fp_FogColor >= 0)
3129                         {
3130                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
3131                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
3132                                 else
3133                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
3134                         }
3135                         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);
3136                         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]);
3137                         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]);
3138                         if (r_cg_permutation->fp_RefractColor >= 0) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);
3139                         if (r_cg_permutation->fp_ReflectColor >= 0) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);
3140                         if (r_cg_permutation->fp_ReflectFactor >= 0) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3141                         if (r_cg_permutation->fp_ReflectOffset >= 0) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);
3142                         if (r_cg_permutation->fp_SpecularPower >= 0) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3143                 }
3144                 if (r_cg_permutation->fp_Color_Glow >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3145                 if (r_cg_permutation->fp_Alpha >= 0) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);
3146                 if (r_cg_permutation->fp_EyePosition >= 0) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3147                 if (r_cg_permutation->fp_Color_Pants >= 0)
3148                 {
3149                         if (rsurface.texture->pantstexture)
3150                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3151                         else
3152                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
3153                 }
3154                 if (r_cg_permutation->fp_Color_Shirt >= 0)
3155                 {
3156                         if (rsurface.texture->shirttexture)
3157                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3158                         else
3159                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
3160                 }
3161                 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]);
3162                 if (r_cg_permutation->fp_FogPlaneViewDist >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);
3163                 if (r_cg_permutation->fp_FogRangeRecip >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);
3164                 if (r_cg_permutation->fp_FogHeightFade >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);
3165                 if (r_cg_permutation->fp_OffsetMapping_Scale >= 0) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
3166                 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]);
3167
3168         //      if (r_cg_permutation->fp_Texture_First          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First          , R_GetTexture(r_texture_white                                     ));
3169         //      if (r_cg_permutation->fp_Texture_Second         ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second         , R_GetTexture(r_texture_white                                     ));
3170         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_GammaRamps     , R_GetTexture(r_texture_gammaramps                                ));
3171                 if (r_cg_permutation->fp_Texture_Normal         ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Normal         , R_GetTexture(rsurface.texture->nmaptexture                       ));
3172                 if (r_cg_permutation->fp_Texture_Color          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Color          , R_GetTexture(rsurface.texture->basetexture                       ));
3173                 if (r_cg_permutation->fp_Texture_Gloss          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Gloss          , R_GetTexture(rsurface.texture->glosstexture                      ));
3174                 if (r_cg_permutation->fp_Texture_Glow           ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Glow           , R_GetTexture(rsurface.texture->glowtexture                       ));
3175                 if (r_cg_permutation->fp_Texture_SecondaryNormal) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryNormal, R_GetTexture(rsurface.texture->backgroundnmaptexture             ));
3176                 if (r_cg_permutation->fp_Texture_SecondaryColor ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryColor , R_GetTexture(rsurface.texture->backgroundbasetexture             ));
3177                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryGloss , R_GetTexture(rsurface.texture->backgroundglosstexture            ));
3178                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryGlow  , R_GetTexture(rsurface.texture->backgroundglowtexture             ));
3179                 if (r_cg_permutation->fp_Texture_Pants          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Pants          , R_GetTexture(rsurface.texture->pantstexture                      ));
3180                 if (r_cg_permutation->fp_Texture_Shirt          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Shirt          , R_GetTexture(rsurface.texture->shirttexture                      ));
3181                 if (r_cg_permutation->fp_Texture_FogMask        ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_FogMask        , R_GetTexture(r_texture_fogattenuation                            ));
3182                 if (r_cg_permutation->fp_Texture_Lightmap       ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Lightmap       , R_GetTexture(r_texture_white                                     ));
3183                 if (r_cg_permutation->fp_Texture_Deluxemap      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Deluxemap      , R_GetTexture(r_texture_blanknormalmap                            ));
3184                 if (r_cg_permutation->fp_Texture_Attenuation    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Attenuation    , R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3185                 if (r_cg_permutation->fp_Texture_Refraction     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Refraction     , R_GetTexture(r_texture_white                                     ));
3186                 if (r_cg_permutation->fp_Texture_Reflection     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Reflection     , R_GetTexture(r_texture_white                                     ));
3187                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDepth    , R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3188                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3189                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDiffuse  , R_GetTexture(r_shadow_prepasslightingdiffusetexture              ));
3190                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenSpecular , R_GetTexture(r_shadow_prepasslightingspeculartexture             ));
3191                 if (rsurface.rtlight)
3192                 {
3193                         if (r_cg_permutation->fp_Texture_Cube       ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Cube           , R_GetTexture(rsurface.rtlight->currentcubemap                    ));
3194                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapRect  , R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3195                         if (r_shadow_usingshadowmapcube)
3196                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapCube  , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
3197                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMap2D    , R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3198                         if (r_cg_permutation->fp_Texture_CubeProjection ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture                      ));
3199                 }
3200
3201                 CHECKGLERROR
3202 #endif
3203                 break;
3204         case RENDERPATH_GL13:
3205         case RENDERPATH_GL11:
3206                 break;
3207         }
3208 }
3209
3210 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3211 {
3212         // select a permutation of the lighting shader appropriate to this
3213         // combination of texture, entity, light source, and fogging, only use the
3214         // minimum features necessary to avoid wasting rendering time in the
3215         // fragment shader on features that are not being used
3216         unsigned int permutation = 0;
3217         unsigned int mode = 0;
3218         const float *lightcolorbase = rtlight->currentcolor;
3219         float ambientscale = rtlight->ambientscale;
3220         float diffusescale = rtlight->diffusescale;
3221         float specularscale = rtlight->specularscale;
3222         // this is the location of the light in view space
3223         vec3_t viewlightorigin;
3224         // this transforms from view space (camera) to light space (cubemap)
3225         matrix4x4_t viewtolight;
3226         matrix4x4_t lighttoview;
3227         float viewtolight16f[16];
3228         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3229         // light source
3230         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3231         if (rtlight->currentcubemap != r_texture_whitecube)
3232                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3233         if (diffusescale > 0)
3234                 permutation |= SHADERPERMUTATION_DIFFUSE;
3235         if (specularscale > 0)
3236         {
3237                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3238                 if (r_shadow_glossexact.integer)
3239                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
3240         }
3241         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
3242         {
3243                 if (r_shadow_usingshadowmaprect)
3244                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
3245                 if (r_shadow_usingshadowmap2d)
3246                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3247                 if (r_shadow_usingshadowmapcube)
3248                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
3249                 else if(r_shadow_shadowmapvsdct)
3250                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3251
3252                 if (r_shadow_shadowmapsampler)
3253                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3254                 if (r_shadow_shadowmappcf > 1)
3255                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3256                 else if (r_shadow_shadowmappcf)
3257                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3258         }
3259         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3260         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3261         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3262         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3263         switch(vid.renderpath)
3264         {
3265         case RENDERPATH_GL20:
3266                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3267                 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3268                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3269                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3270                 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);
3271                 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);
3272                 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);
3273                 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]);
3274                 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]);
3275                 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));
3276                 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]);
3277
3278                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       ,          R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3279                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH    , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3280                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3281                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBindAll(GL20TU_CUBE           , 0, 0,    R_GetTexture(rsurface.rtlight->currentcubemap                    ), 0);
3282                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT  , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3283                 if (r_shadow_usingshadowmapcube)
3284                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE  , 0, 0,    R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
3285                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       ,          R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3286                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0,    R_GetTexture(r_shadow_shadowmapvsdcttexture                      ), 0);
3287                 break;
3288         case RENDERPATH_CGGL:
3289 #ifdef SUPPORTCG
3290                 R_SetupShader_SetPermutationCG(mode, permutation);
3291                 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);
3292                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3293                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);
3294                 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);
3295                 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);
3296                 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);
3297                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3298                 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]);
3299                 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));
3300                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3301
3302                 if (r_cg_permutation->fp_Texture_Attenuation      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Attenuation    , R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3303                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDepth    , R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3304                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3305                 if (r_cg_permutation->fp_Texture_Cube             ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Cube           , R_GetTexture(rsurface.rtlight->currentcubemap                    ));
3306                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapRect  , R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3307                 if (r_shadow_usingshadowmapcube)
3308                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapCube  , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
3309                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMap2D    , R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3310                 if (r_cg_permutation->fp_Texture_CubeProjection   ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture                      ));
3311 #endif
3312                 break;
3313         case RENDERPATH_GL13:
3314         case RENDERPATH_GL11:
3315                 break;
3316         }
3317 }
3318
3319 #define SKINFRAME_HASH 1024
3320
3321 typedef struct
3322 {
3323         int loadsequence; // incremented each level change
3324         memexpandablearray_t array;
3325         skinframe_t *hash[SKINFRAME_HASH];
3326 }
3327 r_skinframe_t;
3328 r_skinframe_t r_skinframe;
3329
3330 void R_SkinFrame_PrepareForPurge(void)
3331 {
3332         r_skinframe.loadsequence++;
3333         // wrap it without hitting zero
3334         if (r_skinframe.loadsequence >= 200)
3335                 r_skinframe.loadsequence = 1;
3336 }
3337
3338 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3339 {
3340         if (!skinframe)
3341                 return;
3342         // mark the skinframe as used for the purging code
3343         skinframe->loadsequence = r_skinframe.loadsequence;
3344 }
3345
3346 void R_SkinFrame_Purge(void)
3347 {
3348         int i;
3349         skinframe_t *s;
3350         for (i = 0;i < SKINFRAME_HASH;i++)
3351         {
3352                 for (s = r_skinframe.hash[i];s;s = s->next)
3353                 {
3354                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3355                         {
3356                                 if (s->merged == s->base)
3357                                         s->merged = NULL;
3358                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3359                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3360                                 R_PurgeTexture(s->merged);s->merged = NULL;
3361                                 R_PurgeTexture(s->base  );s->base   = NULL;
3362                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3363                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3364                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3365                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3366                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3367                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3368                                 s->loadsequence = 0;
3369                         }
3370                 }
3371         }
3372 }
3373
3374 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3375         skinframe_t *item;
3376         char basename[MAX_QPATH];
3377
3378         Image_StripImageExtension(name, basename, sizeof(basename));
3379
3380         if( last == NULL ) {
3381                 int hashindex;
3382                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3383                 item = r_skinframe.hash[hashindex];
3384         } else {
3385                 item = last->next;
3386         }
3387
3388         // linearly search through the hash bucket
3389         for( ; item ; item = item->next ) {
3390                 if( !strcmp( item->basename, basename ) ) {
3391                         return item;
3392                 }
3393         }
3394         return NULL;
3395 }
3396
3397 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3398 {
3399         skinframe_t *item;
3400         int hashindex;
3401         char basename[MAX_QPATH];
3402
3403         Image_StripImageExtension(name, basename, sizeof(basename));
3404
3405         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3406         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3407                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3408                         break;
3409
3410         if (!item) {
3411                 rtexture_t *dyntexture;
3412                 // check whether its a dynamic texture
3413                 dyntexture = CL_GetDynTexture( basename );
3414                 if (!add && !dyntexture)
3415                         return NULL;
3416                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3417                 memset(item, 0, sizeof(*item));
3418                 strlcpy(item->basename, basename, sizeof(item->basename));
3419                 item->base = dyntexture; // either NULL or dyntexture handle
3420                 item->textureflags = textureflags;
3421                 item->comparewidth = comparewidth;
3422                 item->compareheight = compareheight;
3423                 item->comparecrc = comparecrc;
3424                 item->next = r_skinframe.hash[hashindex];
3425                 r_skinframe.hash[hashindex] = item;
3426         }
3427         else if( item->base == NULL )
3428         {
3429                 rtexture_t *dyntexture;
3430                 // check whether its a dynamic texture
3431                 // 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]
3432                 dyntexture = CL_GetDynTexture( basename );
3433                 item->base = dyntexture; // either NULL or dyntexture handle
3434         }
3435
3436         R_SkinFrame_MarkUsed(item);
3437         return item;
3438 }
3439
3440 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3441         { \
3442                 unsigned long long avgcolor[5], wsum; \
3443                 int pix, comp, w; \
3444                 avgcolor[0] = 0; \
3445                 avgcolor[1] = 0; \
3446                 avgcolor[2] = 0; \
3447                 avgcolor[3] = 0; \
3448                 avgcolor[4] = 0; \
3449                 wsum = 0; \
3450                 for(pix = 0; pix < cnt; ++pix) \
3451                 { \
3452                         w = 0; \
3453                         for(comp = 0; comp < 3; ++comp) \
3454                                 w += getpixel; \
3455                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3456                         { \
3457                                 ++wsum; \
3458                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3459                                 w = getpixel; \
3460                                 for(comp = 0; comp < 3; ++comp) \
3461                                         avgcolor[comp] += getpixel * w; \
3462                                 avgcolor[3] += w; \
3463                         } \
3464                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3465                         avgcolor[4] += getpixel; \
3466                 } \
3467                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3468                         avgcolor[3] = 1; \
3469                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3470                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3471                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3472                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3473         }
3474
3475 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3476 {
3477         int j;
3478         unsigned char *pixels;
3479         unsigned char *bumppixels;
3480         unsigned char *basepixels = NULL;
3481         int basepixels_width;
3482         int basepixels_height;
3483         skinframe_t *skinframe;
3484
3485         if (cls.state == ca_dedicated)
3486                 return NULL;
3487
3488         // return an existing skinframe if already loaded
3489         // if loading of the first image fails, don't make a new skinframe as it
3490         // would cause all future lookups of this to be missing
3491         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3492         if (skinframe && skinframe->base)
3493                 return skinframe;
3494
3495         basepixels = loadimagepixelsbgra(name, complain, true);
3496         if (basepixels == NULL)
3497                 return NULL;
3498
3499         if (developer_loading.integer)
3500                 Con_Printf("loading skin \"%s\"\n", name);
3501
3502         // we've got some pixels to store, so really allocate this new texture now
3503         if (!skinframe)
3504                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3505         skinframe->stain = NULL;
3506         skinframe->merged = NULL;
3507         skinframe->base = r_texture_notexture;
3508         skinframe->pants = NULL;
3509         skinframe->shirt = NULL;
3510         skinframe->nmap = r_texture_blanknormalmap;
3511         skinframe->gloss = NULL;
3512         skinframe->glow = NULL;
3513         skinframe->fog = NULL;
3514         skinframe->hasalpha = false;
3515
3516         basepixels_width = image_width;
3517         basepixels_height = image_height;
3518         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);
3519
3520         if (textureflags & TEXF_ALPHA)
3521         {
3522                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3523                 {
3524                         if (basepixels[j] < 255)
3525                         {
3526                                 skinframe->hasalpha = true;
3527                                 break;
3528                         }
3529                 }
3530                 if (r_loadfog && skinframe->hasalpha)
3531                 {
3532                         // has transparent pixels
3533                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3534                         for (j = 0;j < image_width * image_height * 4;j += 4)
3535                         {
3536                                 pixels[j+0] = 255;
3537                                 pixels[j+1] = 255;
3538                                 pixels[j+2] = 255;
3539                                 pixels[j+3] = basepixels[j+3];
3540                         }
3541                         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);
3542                         Mem_Free(pixels);
3543                 }
3544         }
3545
3546         R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3547         //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]);
3548
3549         // _norm is the name used by tenebrae and has been adopted as standard
3550         if (r_loadnormalmap)
3551         {
3552                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
3553                 {
3554                         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);
3555                         Mem_Free(pixels);
3556                         pixels = NULL;
3557                 }
3558                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
3559                 {
3560                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3561                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3562                         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);
3563                         Mem_Free(pixels);
3564                         Mem_Free(bumppixels);
3565                 }
3566                 else if (r_shadow_bumpscale_basetexture.value > 0)
3567                 {
3568                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3569                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3570                         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);
3571                         Mem_Free(pixels);
3572                 }
3573         }
3574         // _luma is supported for tenebrae compatibility
3575         // (I think it's a very stupid name, but oh well)
3576         // _glow is the preferred name
3577         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;}
3578         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;}
3579         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;}
3580         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;}
3581
3582         if (basepixels)
3583                 Mem_Free(basepixels);
3584
3585         return skinframe;
3586 }
3587
3588 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3589 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3590 {
3591         int i;
3592         unsigned char *temp1, *temp2;
3593         skinframe_t *skinframe;
3594
3595         if (cls.state == ca_dedicated)
3596                 return NULL;
3597
3598         // if already loaded just return it, otherwise make a new skinframe
3599         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3600         if (skinframe && skinframe->base)
3601                 return skinframe;
3602
3603         skinframe->stain = NULL;
3604         skinframe->merged = NULL;
3605         skinframe->base = r_texture_notexture;
3606         skinframe->pants = NULL;
3607         skinframe->shirt = NULL;
3608         skinframe->nmap = r_texture_blanknormalmap;
3609         skinframe->gloss = NULL;
3610         skinframe->glow = NULL;
3611         skinframe->fog = NULL;
3612         skinframe->hasalpha = false;
3613
3614         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3615         if (!skindata)
3616                 return NULL;
3617
3618         if (developer_loading.integer)
3619                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3620
3621         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3622         {
3623                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3624                 temp2 = temp1 + width * height * 4;
3625                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3626                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3627                 Mem_Free(temp1);
3628         }
3629         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
3630         if (textureflags & TEXF_ALPHA)
3631         {
3632                 for (i = 3;i < width * height * 4;i += 4)
3633                 {
3634                         if (skindata[i] < 255)
3635                         {
3636                                 skinframe->hasalpha = true;
3637                                 break;
3638                         }
3639                 }
3640                 if (r_loadfog && skinframe->hasalpha)
3641                 {
3642                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3643                         memcpy(fogpixels, skindata, width * height * 4);
3644                         for (i = 0;i < width * height * 4;i += 4)
3645                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3646                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
3647                         Mem_Free(fogpixels);
3648                 }
3649         }
3650
3651         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3652         //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]);
3653
3654         return skinframe;
3655 }
3656
3657 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3658 {
3659         int i;
3660         int featuresmask;
3661         skinframe_t *skinframe;
3662
3663         if (cls.state == ca_dedicated)
3664                 return NULL;
3665
3666         // if already loaded just return it, otherwise make a new skinframe
3667         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3668         if (skinframe && skinframe->base)
3669                 return skinframe;
3670
3671         skinframe->stain = NULL;
3672         skinframe->merged = NULL;
3673         skinframe->base = r_texture_notexture;
3674         skinframe->pants = NULL;
3675         skinframe->shirt = NULL;
3676         skinframe->nmap = r_texture_blanknormalmap;
3677         skinframe->gloss = NULL;
3678         skinframe->glow = NULL;
3679         skinframe->fog = NULL;
3680         skinframe->hasalpha = false;
3681
3682         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3683         if (!skindata)
3684                 return NULL;
3685
3686         if (developer_loading.integer)
3687                 Con_Printf("loading quake skin \"%s\"\n", name);
3688
3689         // 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)
3690         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
3691         memcpy(skinframe->qpixels, skindata, width*height);
3692         skinframe->qwidth = width;
3693         skinframe->qheight = height;
3694
3695         featuresmask = 0;
3696         for (i = 0;i < width * height;i++)
3697                 featuresmask |= palette_featureflags[skindata[i]];
3698
3699         skinframe->hasalpha = false;
3700         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3701         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3702         skinframe->qgeneratemerged = true;
3703         skinframe->qgeneratebase = skinframe->qhascolormapping;
3704         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3705
3706         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3707         //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]);
3708
3709         return skinframe;
3710 }
3711
3712 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3713 {
3714         int width;
3715         int height;
3716         unsigned char *skindata;
3717
3718         if (!skinframe->qpixels)
3719                 return;
3720
3721         if (!skinframe->qhascolormapping)
3722                 colormapped = false;
3723
3724         if (colormapped)
3725         {
3726                 if (!skinframe->qgeneratebase)
3727                         return;
3728         }
3729         else
3730         {
3731                 if (!skinframe->qgeneratemerged)
3732                         return;
3733         }
3734
3735         width = skinframe->qwidth;
3736         height = skinframe->qheight;
3737         skindata = skinframe->qpixels;
3738
3739         if (skinframe->qgeneratenmap)
3740         {
3741                 unsigned char *temp1, *temp2;
3742                 skinframe->qgeneratenmap = false;
3743                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3744                 temp2 = temp1 + width * height * 4;
3745                 // use either a custom palette or the quake palette
3746                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3747                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3748                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3749                 Mem_Free(temp1);
3750         }
3751
3752         if (skinframe->qgenerateglow)
3753         {
3754                 skinframe->qgenerateglow = false;
3755                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
3756         }
3757
3758         if (colormapped)
3759         {
3760                 skinframe->qgeneratebase = false;
3761                 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);
3762                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
3763                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
3764         }
3765         else
3766         {
3767                 skinframe->qgeneratemerged = false;
3768                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3769         }
3770
3771         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3772         {
3773                 Mem_Free(skinframe->qpixels);
3774                 skinframe->qpixels = NULL;
3775         }
3776 }
3777
3778 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)
3779 {
3780         int i;
3781         skinframe_t *skinframe;
3782
3783         if (cls.state == ca_dedicated)
3784                 return NULL;
3785
3786         // if already loaded just return it, otherwise make a new skinframe
3787         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3788         if (skinframe && skinframe->base)
3789                 return skinframe;
3790
3791         skinframe->stain = NULL;
3792         skinframe->merged = NULL;
3793         skinframe->base = r_texture_notexture;
3794         skinframe->pants = NULL;
3795         skinframe->shirt = NULL;
3796         skinframe->nmap = r_texture_blanknormalmap;
3797         skinframe->gloss = NULL;
3798         skinframe->glow = NULL;
3799         skinframe->fog = NULL;
3800         skinframe->hasalpha = false;
3801
3802         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3803         if (!skindata)
3804                 return NULL;
3805
3806         if (developer_loading.integer)
3807                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3808
3809         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3810         if (textureflags & TEXF_ALPHA)
3811         {
3812                 for (i = 0;i < width * height;i++)
3813                 {
3814                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3815                         {
3816                                 skinframe->hasalpha = true;
3817                                 break;
3818                         }
3819                 }
3820                 if (r_loadfog && skinframe->hasalpha)
3821                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3822         }
3823
3824         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3825         //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]);
3826
3827         return skinframe;
3828 }
3829
3830 skinframe_t *R_SkinFrame_LoadMissing(void)
3831 {
3832         skinframe_t *skinframe;
3833
3834         if (cls.state == ca_dedicated)
3835                 return NULL;
3836
3837         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3838         skinframe->stain = NULL;
3839         skinframe->merged = NULL;
3840         skinframe->base = r_texture_notexture;
3841         skinframe->pants = NULL;
3842         skinframe->shirt = NULL;
3843         skinframe->nmap = r_texture_blanknormalmap;
3844         skinframe->gloss = NULL;
3845         skinframe->glow = NULL;
3846         skinframe->fog = NULL;
3847         skinframe->hasalpha = false;
3848
3849         skinframe->avgcolor[0] = rand() / RAND_MAX;
3850         skinframe->avgcolor[1] = rand() / RAND_MAX;
3851         skinframe->avgcolor[2] = rand() / RAND_MAX;
3852         skinframe->avgcolor[3] = 1;
3853
3854         return skinframe;
3855 }
3856
3857 void R_Main_FreeViewCache(void)
3858 {
3859         if (r_refdef.viewcache.entityvisible)
3860                 Mem_Free(r_refdef.viewcache.entityvisible);
3861         if (r_refdef.viewcache.world_pvsbits)
3862                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3863         if (r_refdef.viewcache.world_leafvisible)
3864                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3865         if (r_refdef.viewcache.world_surfacevisible)
3866                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3867         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3868 }
3869
3870 void R_Main_ResizeViewCache(void)
3871 {
3872         int numentities = r_refdef.scene.numentities;
3873         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3874         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3875         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3876         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3877         if (r_refdef.viewcache.maxentities < numentities)
3878         {
3879                 r_refdef.viewcache.maxentities = numentities;
3880                 if (r_refdef.viewcache.entityvisible)
3881                         Mem_Free(r_refdef.viewcache.entityvisible);
3882                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3883         }
3884         if (r_refdef.viewcache.world_numclusters != numclusters)
3885         {
3886                 r_refdef.viewcache.world_numclusters = numclusters;
3887                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3888                 if (r_refdef.viewcache.world_pvsbits)
3889                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3890                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3891         }
3892         if (r_refdef.viewcache.world_numleafs != numleafs)
3893         {
3894                 r_refdef.viewcache.world_numleafs = numleafs;
3895                 if (r_refdef.viewcache.world_leafvisible)
3896                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3897                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3898         }
3899         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3900         {
3901                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3902                 if (r_refdef.viewcache.world_surfacevisible)
3903                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3904                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3905         }
3906 }
3907
3908 extern rtexture_t *loadingscreentexture;
3909 void gl_main_start(void)
3910 {
3911         loadingscreentexture = NULL;
3912         r_texture_blanknormalmap = NULL;
3913         r_texture_white = NULL;
3914         r_texture_grey128 = NULL;
3915         r_texture_black = NULL;
3916         r_texture_whitecube = NULL;
3917         r_texture_normalizationcube = NULL;
3918         r_texture_fogattenuation = NULL;
3919         r_texture_gammaramps = NULL;
3920
3921         switch(vid.renderpath)
3922         {
3923         case RENDERPATH_GL20:
3924         case RENDERPATH_CGGL:
3925                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3926                 Cvar_SetValueQuick(&gl_combine, 1);
3927                 Cvar_SetValueQuick(&r_glsl, 1);
3928                 r_loadnormalmap = true;
3929                 r_loadgloss = true;
3930                 r_loadfog = false;
3931                 break;
3932         case RENDERPATH_GL13:
3933                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3934                 Cvar_SetValueQuick(&gl_combine, 1);
3935                 Cvar_SetValueQuick(&r_glsl, 0);
3936                 r_loadnormalmap = false;
3937                 r_loadgloss = false;
3938                 r_loadfog = true;
3939                 break;
3940         case RENDERPATH_GL11:
3941                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3942                 Cvar_SetValueQuick(&gl_combine, 0);
3943                 Cvar_SetValueQuick(&r_glsl, 0);
3944                 r_loadnormalmap = false;
3945                 r_loadgloss = false;
3946                 r_loadfog = true;
3947                 break;
3948         }
3949
3950         R_AnimCache_Free();
3951         R_FrameData_Reset();
3952
3953         r_numqueries = 0;
3954         r_maxqueries = 0;
3955         memset(r_queries, 0, sizeof(r_queries));
3956
3957         r_qwskincache = NULL;
3958         r_qwskincache_size = 0;
3959
3960         // set up r_skinframe loading system for textures
3961         memset(&r_skinframe, 0, sizeof(r_skinframe));
3962         r_skinframe.loadsequence = 1;
3963         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3964
3965         r_main_texturepool = R_AllocTexturePool();
3966         R_BuildBlankTextures();
3967         R_BuildNoTexture();
3968         if (vid.support.arb_texture_cube_map)
3969         {
3970                 R_BuildWhiteCube();
3971                 R_BuildNormalizationCube();
3972         }
3973         r_texture_fogattenuation = NULL;
3974         r_texture_gammaramps = NULL;
3975         //r_texture_fogintensity = NULL;
3976         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3977         memset(&r_waterstate, 0, sizeof(r_waterstate));
3978         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3979         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3980 #ifdef SUPPORTCG
3981         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
3982         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
3983 #endif
3984         memset(&r_svbsp, 0, sizeof (r_svbsp));
3985
3986         r_refdef.fogmasktable_density = 0;
3987 }
3988
3989 void gl_main_shutdown(void)
3990 {
3991         R_AnimCache_Free();
3992         R_FrameData_Reset();
3993
3994         R_Main_FreeViewCache();
3995
3996         if (r_maxqueries)
3997                 qglDeleteQueriesARB(r_maxqueries, r_queries);
3998
3999         r_numqueries = 0;
4000         r_maxqueries = 0;
4001         memset(r_queries, 0, sizeof(r_queries));
4002
4003         r_qwskincache = NULL;
4004         r_qwskincache_size = 0;
4005
4006         // clear out the r_skinframe state
4007         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4008         memset(&r_skinframe, 0, sizeof(r_skinframe));
4009
4010         if (r_svbsp.nodes)
4011                 Mem_Free(r_svbsp.nodes);
4012         memset(&r_svbsp, 0, sizeof (r_svbsp));
4013         R_FreeTexturePool(&r_main_texturepool);
4014         loadingscreentexture = NULL;
4015         r_texture_blanknormalmap = NULL;
4016         r_texture_white = NULL;
4017         r_texture_grey128 = NULL;
4018         r_texture_black = NULL;
4019         r_texture_whitecube = NULL;
4020         r_texture_normalizationcube = NULL;
4021         r_texture_fogattenuation = NULL;
4022         r_texture_gammaramps = NULL;
4023         //r_texture_fogintensity = NULL;
4024         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4025         memset(&r_waterstate, 0, sizeof(r_waterstate));
4026         R_GLSL_Restart_f();
4027 }
4028
4029 extern void CL_ParseEntityLump(char *entitystring);
4030 void gl_main_newmap(void)
4031 {
4032         // FIXME: move this code to client
4033         int l;
4034         char *entities, entname[MAX_QPATH];
4035         if (r_qwskincache)
4036                 Mem_Free(r_qwskincache);
4037         r_qwskincache = NULL;
4038         r_qwskincache_size = 0;
4039         if (cl.worldmodel)
4040         {
4041                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
4042                 l = (int)strlen(entname) - 4;
4043                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
4044                 {
4045                         memcpy(entname + l, ".ent", 5);
4046                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4047                         {
4048                                 CL_ParseEntityLump(entities);
4049                                 Mem_Free(entities);
4050                                 return;
4051                         }
4052                 }
4053                 if (cl.worldmodel->brush.entities)
4054                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4055         }
4056         R_Main_FreeViewCache();
4057
4058         R_FrameData_Reset();
4059 }
4060
4061 void GL_Main_Init(void)
4062 {
4063         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4064
4065         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4066         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4067         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4068         if (gamemode == GAME_NEHAHRA)
4069         {
4070                 Cvar_RegisterVariable (&gl_fogenable);
4071                 Cvar_RegisterVariable (&gl_fogdensity);
4072                 Cvar_RegisterVariable (&gl_fogred);
4073                 Cvar_RegisterVariable (&gl_foggreen);
4074                 Cvar_RegisterVariable (&gl_fogblue);
4075                 Cvar_RegisterVariable (&gl_fogstart);
4076                 Cvar_RegisterVariable (&gl_fogend);
4077                 Cvar_RegisterVariable (&gl_skyclip);
4078         }
4079         Cvar_RegisterVariable(&r_motionblur);
4080         Cvar_RegisterVariable(&r_motionblur_maxblur);
4081         Cvar_RegisterVariable(&r_motionblur_bmin);
4082         Cvar_RegisterVariable(&r_motionblur_vmin);
4083         Cvar_RegisterVariable(&r_motionblur_vmax);
4084         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4085         Cvar_RegisterVariable(&r_motionblur_randomize);
4086         Cvar_RegisterVariable(&r_damageblur);
4087         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4088         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4089         Cvar_RegisterVariable(&r_equalize_entities_by);
4090         Cvar_RegisterVariable(&r_equalize_entities_to);
4091         Cvar_RegisterVariable(&r_depthfirst);
4092         Cvar_RegisterVariable(&r_useinfinitefarclip);
4093         Cvar_RegisterVariable(&r_farclip_base);
4094         Cvar_RegisterVariable(&r_farclip_world);
4095         Cvar_RegisterVariable(&r_nearclip);
4096         Cvar_RegisterVariable(&r_showbboxes);
4097         Cvar_RegisterVariable(&r_showsurfaces);
4098         Cvar_RegisterVariable(&r_showtris);
4099         Cvar_RegisterVariable(&r_shownormals);
4100         Cvar_RegisterVariable(&r_showlighting);
4101         Cvar_RegisterVariable(&r_showshadowvolumes);
4102         Cvar_RegisterVariable(&r_showcollisionbrushes);
4103         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4104         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4105         Cvar_RegisterVariable(&r_showdisabledepthtest);
4106         Cvar_RegisterVariable(&r_drawportals);
4107         Cvar_RegisterVariable(&r_drawentities);
4108         Cvar_RegisterVariable(&r_cullentities_trace);
4109         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4110         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4111         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4112         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4113         Cvar_RegisterVariable(&r_drawviewmodel);
4114         Cvar_RegisterVariable(&r_speeds);
4115         Cvar_RegisterVariable(&r_fullbrights);
4116         Cvar_RegisterVariable(&r_wateralpha);
4117         Cvar_RegisterVariable(&r_dynamic);
4118         Cvar_RegisterVariable(&r_fullbright);
4119         Cvar_RegisterVariable(&r_shadows);
4120         Cvar_RegisterVariable(&r_shadows_darken);
4121         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4122         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4123         Cvar_RegisterVariable(&r_shadows_throwdistance);
4124         Cvar_RegisterVariable(&r_shadows_throwdirection);
4125         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4126         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4127         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4128         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4129         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4130         Cvar_RegisterVariable(&r_fog_exp2);
4131         Cvar_RegisterVariable(&r_drawfog);
4132         Cvar_RegisterVariable(&r_transparentdepthmasking);
4133         Cvar_RegisterVariable(&r_textureunits);
4134         Cvar_RegisterVariable(&gl_combine);
4135         Cvar_RegisterVariable(&r_glsl);
4136         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4137         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4138         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4139         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4140         Cvar_RegisterVariable(&r_glsl_postprocess);
4141         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4142         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4143         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4144         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4145         Cvar_RegisterVariable(&r_water);
4146         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4147         Cvar_RegisterVariable(&r_water_clippingplanebias);
4148         Cvar_RegisterVariable(&r_water_refractdistort);
4149         Cvar_RegisterVariable(&r_water_reflectdistort);
4150         Cvar_RegisterVariable(&r_lerpsprites);
4151         Cvar_RegisterVariable(&r_lerpmodels);
4152         Cvar_RegisterVariable(&r_lerplightstyles);
4153         Cvar_RegisterVariable(&r_waterscroll);
4154         Cvar_RegisterVariable(&r_bloom);
4155         Cvar_RegisterVariable(&r_bloom_colorscale);
4156         Cvar_RegisterVariable(&r_bloom_brighten);
4157         Cvar_RegisterVariable(&r_bloom_blur);
4158         Cvar_RegisterVariable(&r_bloom_resolution);
4159         Cvar_RegisterVariable(&r_bloom_colorexponent);
4160         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4161         Cvar_RegisterVariable(&r_hdr);
4162         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4163         Cvar_RegisterVariable(&r_hdr_glowintensity);
4164         Cvar_RegisterVariable(&r_hdr_range);
4165         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4166         Cvar_RegisterVariable(&developer_texturelogging);
4167         Cvar_RegisterVariable(&gl_lightmaps);
4168         Cvar_RegisterVariable(&r_test);
4169         Cvar_RegisterVariable(&r_batchmode);
4170         Cvar_RegisterVariable(&r_glsl_saturation);
4171         Cvar_RegisterVariable(&r_framedatasize);
4172         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4173                 Cvar_SetValue("r_fullbrights", 0);
4174         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
4175
4176         Cvar_RegisterVariable(&r_track_sprites);
4177         Cvar_RegisterVariable(&r_track_sprites_flags);
4178         Cvar_RegisterVariable(&r_track_sprites_scalew);
4179         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4180 }
4181
4182 extern void R_Textures_Init(void);
4183 extern void GL_Draw_Init(void);
4184 extern void GL_Main_Init(void);
4185 extern void R_Shadow_Init(void);
4186 extern void R_Sky_Init(void);
4187 extern void GL_Surf_Init(void);
4188 extern void R_Particles_Init(void);
4189 extern void R_Explosion_Init(void);
4190 extern void gl_backend_init(void);
4191 extern void Sbar_Init(void);
4192 extern void R_LightningBeams_Init(void);
4193 extern void Mod_RenderInit(void);
4194
4195 void Render_Init(void)
4196 {
4197         gl_backend_init();
4198         R_Textures_Init();
4199         GL_Main_Init();
4200         GL_Draw_Init();
4201         R_Shadow_Init();
4202         R_Sky_Init();
4203         GL_Surf_Init();
4204         Sbar_Init();
4205         R_Particles_Init();
4206         R_Explosion_Init();
4207         R_LightningBeams_Init();
4208         Mod_RenderInit();
4209 }
4210
4211 /*
4212 ===============
4213 GL_Init
4214 ===============
4215 */
4216 extern char *ENGINE_EXTENSIONS;
4217 void GL_Init (void)
4218 {
4219         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4220         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4221         gl_version = (const char *)qglGetString(GL_VERSION);
4222         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4223
4224         if (!gl_extensions)
4225                 gl_extensions = "";
4226         if (!gl_platformextensions)
4227                 gl_platformextensions = "";
4228
4229         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4230         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4231         Con_Printf("GL_VERSION: %s\n", gl_version);
4232         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4233         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4234
4235         VID_CheckExtensions();
4236
4237         // LordHavoc: report supported extensions
4238         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4239
4240         // clear to black (loading plaque will be seen over this)
4241         CHECKGLERROR
4242         qglClearColor(0,0,0,1);CHECKGLERROR
4243         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
4244 }
4245
4246 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4247 {
4248         int i;
4249         mplane_t *p;
4250         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4251         {
4252                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4253                 if (i == 4)
4254                         continue;
4255                 p = r_refdef.view.frustum + i;
4256                 switch(p->signbits)
4257                 {
4258                 default:
4259                 case 0:
4260                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4261                                 return true;
4262                         break;
4263                 case 1:
4264                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4265                                 return true;
4266                         break;
4267                 case 2:
4268                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4269                                 return true;
4270                         break;
4271                 case 3:
4272                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4273                                 return true;
4274                         break;
4275                 case 4:
4276                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4277                                 return true;
4278                         break;
4279                 case 5:
4280                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4281                                 return true;
4282                         break;
4283                 case 6:
4284                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4285                                 return true;
4286                         break;
4287                 case 7:
4288                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4289                                 return true;
4290                         break;
4291                 }
4292         }
4293         return false;
4294 }
4295
4296 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4297 {
4298         int i;
4299         const mplane_t *p;
4300         for (i = 0;i < numplanes;i++)
4301         {
4302                 p = planes + i;
4303                 switch(p->signbits)
4304                 {
4305                 default:
4306                 case 0:
4307                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4308                                 return true;
4309                         break;
4310                 case 1:
4311                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4312                                 return true;
4313                         break;
4314                 case 2:
4315                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4316                                 return true;
4317                         break;
4318                 case 3:
4319                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4320                                 return true;
4321                         break;
4322                 case 4:
4323                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4324                                 return true;
4325                         break;
4326                 case 5:
4327                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4328                                 return true;
4329                         break;
4330                 case 6:
4331                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4332                                 return true;
4333                         break;
4334                 case 7:
4335                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4336                                 return true;
4337                         break;
4338                 }
4339         }
4340         return false;
4341 }
4342
4343 //==================================================================================
4344
4345 // LordHavoc: this stores temporary data used within the same frame
4346
4347 qboolean r_framedata_failed;
4348 static size_t r_framedata_size;
4349 static size_t r_framedata_current;
4350 static void *r_framedata_base;
4351
4352 void R_FrameData_Reset(void)
4353 {
4354         if (r_framedata_base);
4355                 Mem_Free(r_framedata_base);
4356         r_framedata_base = NULL;
4357         r_framedata_size = 0;
4358         r_framedata_current = 0;
4359         r_framedata_failed = false;
4360 }
4361
4362 void R_FrameData_NewFrame(void)
4363 {
4364         size_t wantedsize;
4365         if (r_framedata_failed)
4366                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
4367         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4368         wantedsize = bound(65536, wantedsize, 128*1024*1024);
4369         if (r_framedata_size != wantedsize)
4370         {
4371                 r_framedata_size = wantedsize;
4372                 if (r_framedata_base);
4373                         Mem_Free(r_framedata_base);
4374                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
4375         }
4376         r_framedata_current = 0;
4377         r_framedata_failed = false;
4378 }
4379
4380 void *R_FrameData_Alloc(size_t size)
4381 {
4382         void *data;
4383
4384         // align to 16 byte boundary
4385         size = (size + 15) & ~15;
4386         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
4387         r_framedata_current += size;
4388
4389         // check overflow
4390         if (r_framedata_current > r_framedata_size)
4391                 r_framedata_failed = true;
4392
4393         // return NULL on everything after a failure
4394         if (r_framedata_failed)
4395                 return NULL;
4396
4397         return data;
4398 }
4399
4400 void *R_FrameData_Store(size_t size, void *data)
4401 {
4402         void *d = R_FrameData_Alloc(size);
4403         if (d)
4404                 memcpy(d, data, size);
4405         return d;
4406 }
4407
4408 //==================================================================================
4409
4410 // LordHavoc: animcache originally written by Echon, rewritten since then
4411
4412 /**
4413  * Animation cache prevents re-generating mesh data for an animated model
4414  * multiple times in one frame for lighting, shadowing, reflections, etc.
4415  */
4416
4417 void R_AnimCache_Free(void)
4418 {
4419 }
4420
4421 void R_AnimCache_ClearCache(void)
4422 {
4423         int i;
4424         entity_render_t *ent;
4425
4426         for (i = 0;i < r_refdef.scene.numentities;i++)
4427         {
4428                 ent = r_refdef.scene.entities[i];
4429                 ent->animcache_vertex3f = NULL;
4430                 ent->animcache_normal3f = NULL;
4431                 ent->animcache_svector3f = NULL;
4432                 ent->animcache_tvector3f = NULL;
4433         }
4434 }
4435
4436 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4437 {
4438         dp_model_t *model = ent->model;
4439         int numvertices;
4440         // see if it's already cached this frame
4441         if (ent->animcache_vertex3f)
4442         {
4443                 // add normals/tangents if needed
4444                 if (wantnormals || wanttangents)
4445                 {
4446                         if (ent->animcache_normal3f)
4447                                 wantnormals = false;
4448                         if (ent->animcache_svector3f)
4449                                 wanttangents = false;
4450                         if (wantnormals || wanttangents)
4451                         {
4452                                 numvertices = model->surfmesh.num_vertices;
4453                                 if (wantnormals)
4454                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4455                                 if (wanttangents)
4456                                 {
4457                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4458                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4459                                 }
4460                                 if (!r_framedata_failed)
4461                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4462                         }
4463                 }
4464         }
4465         else
4466         {
4467                 // see if this ent is worth caching
4468                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4469                         return false;
4470                 // get some memory for this entity and generate mesh data
4471                 numvertices = model->surfmesh.num_vertices;
4472                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4473                 if (wantnormals)
4474                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4475                 if (wanttangents)
4476                 {
4477                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4478                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4479                 }
4480                 if (!r_framedata_failed)
4481                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4482         }
4483         return !r_framedata_failed;
4484 }
4485
4486 void R_AnimCache_CacheVisibleEntities(void)
4487 {
4488         int i;
4489         qboolean wantnormals = !r_showsurfaces.integer;
4490         qboolean wanttangents = !r_showsurfaces.integer;
4491
4492         switch(vid.renderpath)
4493         {
4494         case RENDERPATH_GL20:
4495         case RENDERPATH_CGGL:
4496                 break;
4497         case RENDERPATH_GL13:
4498         case RENDERPATH_GL11:
4499                 wanttangents = false;
4500                 break;
4501         }
4502
4503         // TODO: thread this
4504         // NOTE: R_PrepareRTLights() also caches entities
4505
4506         for (i = 0;i < r_refdef.scene.numentities;i++)
4507                 if (r_refdef.viewcache.entityvisible[i])
4508                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4509
4510         if (r_shadows.integer)
4511                 for (i = 0;i < r_refdef.scene.numentities;i++)
4512                         if (!r_refdef.viewcache.entityvisible[i])
4513                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
4514 }
4515
4516 //==================================================================================
4517
4518 static void R_View_UpdateEntityLighting (void)
4519 {
4520         int i;
4521         entity_render_t *ent;
4522         vec3_t tempdiffusenormal, avg;
4523         vec_t f, fa, fd, fdd;
4524
4525         for (i = 0;i < r_refdef.scene.numentities;i++)
4526         {
4527                 ent = r_refdef.scene.entities[i];
4528
4529                 // skip unseen models
4530                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
4531                         continue;
4532
4533                 // skip bsp models
4534                 if (ent->model && ent->model->brush.num_leafs)
4535                 {
4536                         // TODO: use modellight for r_ambient settings on world?
4537                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4538                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4539                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4540                         continue;
4541                 }
4542
4543                 // fetch the lighting from the worldmodel data
4544                 VectorClear(ent->modellight_ambient);
4545                 VectorClear(ent->modellight_diffuse);
4546                 VectorClear(tempdiffusenormal);
4547                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4548                 {
4549                         vec3_t org;
4550                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4551                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
4552                         if(ent->flags & RENDER_EQUALIZE)
4553                         {
4554                                 // first fix up ambient lighting...
4555                                 if(r_equalize_entities_minambient.value > 0)
4556                                 {
4557                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4558                                         if(fd > 0)
4559                                         {
4560                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4561                                                 if(fa < r_equalize_entities_minambient.value * fd)
4562                                                 {
4563                                                         // solve:
4564                                                         //   fa'/fd' = minambient
4565                                                         //   fa'+0.25*fd' = fa+0.25*fd
4566                                                         //   ...
4567                                                         //   fa' = fd' * minambient
4568                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4569                                                         //   ...
4570                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4571                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4572                                                         //   ...
4573                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4574                                                         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
4575                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4576                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4577                                                 }
4578                                         }
4579                                 }
4580
4581                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4582                                 {
4583                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
4584                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
4585                                         if(f > 0)
4586                                         {
4587                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
4588                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
4589                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4590                                         }
4591                                 }
4592                         }
4593                 }
4594                 else // highly rare
4595                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4596
4597                 // move the light direction into modelspace coordinates for lighting code
4598                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4599                 if(VectorLength2(ent->modellight_lightdir) == 0)
4600                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4601                 VectorNormalize(ent->modellight_lightdir);
4602         }
4603 }
4604
4605 #define MAX_LINEOFSIGHTTRACES 64
4606
4607 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4608 {
4609         int i;
4610         vec3_t boxmins, boxmaxs;
4611         vec3_t start;
4612         vec3_t end;
4613         dp_model_t *model = r_refdef.scene.worldmodel;
4614
4615         if (!model || !model->brush.TraceLineOfSight)
4616                 return true;
4617
4618         // expand the box a little
4619         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4620         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4621         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4622         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4623         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4624         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4625
4626         // try center
4627         VectorCopy(eye, start);
4628         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4629         if (model->brush.TraceLineOfSight(model, start, end))
4630                 return true;
4631
4632         // try various random positions
4633         for (i = 0;i < numsamples;i++)
4634         {
4635                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4636                 if (model->brush.TraceLineOfSight(model, start, end))
4637                         return true;
4638         }
4639
4640         return false;
4641 }
4642
4643
4644 static void R_View_UpdateEntityVisible (void)
4645 {
4646         int i;
4647         int renderimask;
4648         int samples;
4649         entity_render_t *ent;
4650
4651         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
4652         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4653         {
4654                 // worldmodel can check visibility
4655                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4656                 for (i = 0;i < r_refdef.scene.numentities;i++)
4657                 {
4658                         ent = r_refdef.scene.entities[i];
4659                         if (!(ent->flags & renderimask))
4660                         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)))
4661                         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))
4662                                 r_refdef.viewcache.entityvisible[i] = true;
4663                 }
4664                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
4665                 {
4666                         for (i = 0;i < r_refdef.scene.numentities;i++)
4667                         {
4668                                 ent = r_refdef.scene.entities[i];
4669                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4670                                 {
4671                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4672                                         if (samples < 0)
4673                                                 continue; // temp entities do pvs only
4674                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4675                                                 ent->last_trace_visibility = realtime;
4676                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4677                                                 r_refdef.viewcache.entityvisible[i] = 0;
4678                                 }
4679                         }
4680                 }
4681         }
4682         else
4683         {
4684                 // no worldmodel or it can't check visibility
4685                 for (i = 0;i < r_refdef.scene.numentities;i++)
4686                 {
4687                         ent = r_refdef.scene.entities[i];
4688                         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));
4689                 }
4690         }
4691 }
4692
4693 /// only used if skyrendermasked, and normally returns false
4694 int R_DrawBrushModelsSky (void)
4695 {
4696         int i, sky;
4697         entity_render_t *ent;
4698
4699         sky = false;
4700         for (i = 0;i < r_refdef.scene.numentities;i++)
4701         {
4702                 if (!r_refdef.viewcache.entityvisible[i])
4703                         continue;
4704                 ent = r_refdef.scene.entities[i];
4705                 if (!ent->model || !ent->model->DrawSky)
4706                         continue;
4707                 ent->model->DrawSky(ent);
4708                 sky = true;
4709         }
4710         return sky;
4711 }
4712
4713 static void R_DrawNoModel(entity_render_t *ent);
4714 static void R_DrawModels(void)
4715 {
4716         int i;
4717         entity_render_t *ent;
4718
4719         for (i = 0;i < r_refdef.scene.numentities;i++)
4720         {
4721                 if (!r_refdef.viewcache.entityvisible[i])
4722                         continue;
4723                 ent = r_refdef.scene.entities[i];
4724                 r_refdef.stats.entities++;
4725                 if (ent->model && ent->model->Draw != NULL)
4726                         ent->model->Draw(ent);
4727                 else
4728                         R_DrawNoModel(ent);
4729         }
4730 }
4731
4732 static void R_DrawModelsDepth(void)
4733 {
4734         int i;
4735         entity_render_t *ent;
4736
4737         for (i = 0;i < r_refdef.scene.numentities;i++)
4738         {
4739                 if (!r_refdef.viewcache.entityvisible[i])
4740                         continue;
4741                 ent = r_refdef.scene.entities[i];
4742                 if (ent->model && ent->model->DrawDepth != NULL)
4743                         ent->model->DrawDepth(ent);
4744         }
4745 }
4746
4747 static void R_DrawModelsDebug(void)
4748 {
4749         int i;
4750         entity_render_t *ent;
4751
4752         for (i = 0;i < r_refdef.scene.numentities;i++)
4753         {
4754                 if (!r_refdef.viewcache.entityvisible[i])
4755                         continue;
4756                 ent = r_refdef.scene.entities[i];
4757                 if (ent->model && ent->model->DrawDebug != NULL)
4758                         ent->model->DrawDebug(ent);
4759         }
4760 }
4761
4762 static void R_DrawModelsAddWaterPlanes(void)
4763 {
4764         int i;
4765         entity_render_t *ent;
4766
4767         for (i = 0;i < r_refdef.scene.numentities;i++)
4768         {
4769                 if (!r_refdef.viewcache.entityvisible[i])
4770                         continue;
4771                 ent = r_refdef.scene.entities[i];
4772                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4773                         ent->model->DrawAddWaterPlanes(ent);
4774         }
4775 }
4776
4777 static void R_View_SetFrustum(void)
4778 {
4779         int i;
4780         double slopex, slopey;
4781         vec3_t forward, left, up, origin;
4782
4783         // we can't trust r_refdef.view.forward and friends in reflected scenes
4784         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4785
4786 #if 0
4787         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4788         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4789         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4790         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4791         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4792         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4793         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4794         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4795         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4796         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4797         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4798         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4799 #endif
4800
4801 #if 0
4802         zNear = r_refdef.nearclip;
4803         nudge = 1.0 - 1.0 / (1<<23);
4804         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4805         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4806         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4807         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4808         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4809         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4810         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4811         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4812 #endif
4813
4814
4815
4816 #if 0
4817         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4818         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4819         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4820         r_refdef.view.frustum[0].dist = m[15] - m[12];
4821
4822         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4823         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4824         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4825         r_refdef.view.frustum[1].dist = m[15] + m[12];
4826
4827         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4828         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4829         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4830         r_refdef.view.frustum[2].dist = m[15] - m[13];
4831
4832         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4833         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4834         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4835         r_refdef.view.frustum[3].dist = m[15] + m[13];
4836
4837         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4838         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4839         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4840         r_refdef.view.frustum[4].dist = m[15] - m[14];
4841
4842         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4843         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4844         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4845         r_refdef.view.frustum[5].dist = m[15] + m[14];
4846 #endif
4847
4848         if (r_refdef.view.useperspective)
4849         {
4850                 slopex = 1.0 / r_refdef.view.frustum_x;
4851                 slopey = 1.0 / r_refdef.view.frustum_y;
4852                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4853                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
4854                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
4855                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
4856                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4857
4858                 // Leaving those out was a mistake, those were in the old code, and they
4859                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4860                 // I couldn't reproduce it after adding those normalizations. --blub
4861                 VectorNormalize(r_refdef.view.frustum[0].normal);
4862                 VectorNormalize(r_refdef.view.frustum[1].normal);
4863                 VectorNormalize(r_refdef.view.frustum[2].normal);
4864                 VectorNormalize(r_refdef.view.frustum[3].normal);
4865
4866                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4867                 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]);
4868                 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]);
4869                 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]);
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[3]);
4871
4872                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4873                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4874                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4875                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4876                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4877         }
4878         else
4879         {
4880                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4881                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4882                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4883                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4884                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4885                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4886                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4887                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4888                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4889                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4890         }
4891         r_refdef.view.numfrustumplanes = 5;
4892
4893         if (r_refdef.view.useclipplane)
4894         {
4895                 r_refdef.view.numfrustumplanes = 6;
4896                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4897         }
4898
4899         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4900                 PlaneClassify(r_refdef.view.frustum + i);
4901
4902         // LordHavoc: note to all quake engine coders, Quake had a special case
4903         // for 90 degrees which assumed a square view (wrong), so I removed it,
4904         // Quake2 has it disabled as well.
4905
4906         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4907         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4908         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4909         //PlaneClassify(&frustum[0]);
4910
4911         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4912         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4913         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4914         //PlaneClassify(&frustum[1]);
4915
4916         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4917         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4918         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4919         //PlaneClassify(&frustum[2]);
4920
4921         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4922         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4923         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4924         //PlaneClassify(&frustum[3]);
4925
4926         // nearclip plane
4927         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4928         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4929         //PlaneClassify(&frustum[4]);
4930 }
4931
4932 void R_View_Update(void)
4933 {
4934         R_Main_ResizeViewCache();
4935         R_View_SetFrustum();
4936         R_View_WorldVisibility(r_refdef.view.useclipplane);
4937         R_View_UpdateEntityVisible();
4938         R_View_UpdateEntityLighting();
4939 }
4940
4941 void R_SetupView(qboolean allowwaterclippingplane)
4942 {
4943         const float *customclipplane = NULL;
4944         float plane[4];
4945         if (r_refdef.view.useclipplane && allowwaterclippingplane)
4946         {
4947                 // LordHavoc: couldn't figure out how to make this approach the
4948                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4949                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4950                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4951                         dist = r_refdef.view.clipplane.dist;
4952                 plane[0] = r_refdef.view.clipplane.normal[0];
4953                 plane[1] = r_refdef.view.clipplane.normal[1];
4954                 plane[2] = r_refdef.view.clipplane.normal[2];
4955                 plane[3] = dist;
4956                 customclipplane = plane;
4957         }
4958
4959         if (!r_refdef.view.useperspective)
4960                 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);
4961         else if (vid.stencil && r_useinfinitefarclip.integer)
4962                 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);
4963         else
4964                 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);
4965         R_SetViewport(&r_refdef.view.viewport);
4966 }
4967
4968 void R_EntityMatrix(const matrix4x4_t *matrix)
4969 {
4970         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
4971         {
4972                 gl_modelmatrixchanged = false;
4973                 gl_modelmatrix = *matrix;
4974                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
4975                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
4976                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
4977                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
4978                 CHECKGLERROR
4979                 switch(vid.renderpath)
4980                 {
4981                 case RENDERPATH_GL20:
4982                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4983                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4984                         break;
4985                 case RENDERPATH_CGGL:
4986 #ifdef SUPPORTCG
4987                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix >= 0) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4988                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4989 #endif
4990                         break;
4991                 case RENDERPATH_GL13:
4992                 case RENDERPATH_GL11:
4993                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4994                         break;
4995                 }
4996         }
4997 }
4998
4999 void R_ResetViewRendering2D(void)
5000 {
5001         r_viewport_t viewport;
5002         DrawQ_Finish();
5003
5004         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5005         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);
5006         R_SetViewport(&viewport);
5007         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5008         GL_Color(1, 1, 1, 1);
5009         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5010         GL_BlendFunc(GL_ONE, GL_ZERO);
5011         GL_AlphaTest(false);
5012         GL_ScissorTest(false);
5013         GL_DepthMask(false);
5014         GL_DepthRange(0, 1);
5015         GL_DepthTest(false);
5016         R_EntityMatrix(&identitymatrix);
5017         R_Mesh_ResetTextureState();
5018         GL_PolygonOffset(0, 0);
5019         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5020         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5021         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
5022         qglStencilMask(~0);CHECKGLERROR
5023         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
5024         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
5025         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
5026 }
5027
5028 void R_ResetViewRendering3D(void)
5029 {
5030         DrawQ_Finish();
5031
5032         R_SetupView(true);
5033         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5034         GL_Color(1, 1, 1, 1);
5035         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5036         GL_BlendFunc(GL_ONE, GL_ZERO);
5037         GL_AlphaTest(false);
5038         GL_ScissorTest(true);
5039         GL_DepthMask(true);
5040         GL_DepthRange(0, 1);
5041         GL_DepthTest(true);
5042         R_EntityMatrix(&identitymatrix);
5043         R_Mesh_ResetTextureState();
5044         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5045         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5046         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5047         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
5048         qglStencilMask(~0);CHECKGLERROR
5049         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
5050         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
5051         GL_CullFace(r_refdef.view.cullface_back);
5052 }
5053
5054 void R_RenderScene(void);
5055 void R_RenderWaterPlanes(void);
5056
5057 static void R_Water_StartFrame(void)
5058 {
5059         int i;
5060         int waterwidth, waterheight, texturewidth, textureheight;
5061         r_waterstate_waterplane_t *p;
5062
5063         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5064                 return;
5065
5066         switch(vid.renderpath)
5067         {
5068         case RENDERPATH_GL20:
5069         case RENDERPATH_CGGL:
5070                 break;
5071         case RENDERPATH_GL13:
5072         case RENDERPATH_GL11:
5073                 return;
5074         }
5075
5076         // set waterwidth and waterheight to the water resolution that will be
5077         // used (often less than the screen resolution for faster rendering)
5078         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5079         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5080
5081         // calculate desired texture sizes
5082         // can't use water if the card does not support the texture size
5083         if (!r_water.integer || r_showsurfaces.integer)
5084                 texturewidth = textureheight = waterwidth = waterheight = 0;
5085         else if (vid.support.arb_texture_non_power_of_two)
5086         {
5087                 texturewidth = waterwidth;
5088                 textureheight = waterheight;
5089         }
5090         else
5091         {
5092                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5093                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5094         }
5095
5096         // allocate textures as needed
5097         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
5098         {
5099                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5100                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5101                 {
5102                         if (p->texture_refraction)
5103                                 R_FreeTexture(p->texture_refraction);
5104                         p->texture_refraction = NULL;
5105                         if (p->texture_reflection)
5106                                 R_FreeTexture(p->texture_reflection);
5107                         p->texture_reflection = NULL;
5108                 }
5109                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5110                 r_waterstate.texturewidth = texturewidth;
5111                 r_waterstate.textureheight = textureheight;
5112         }
5113
5114         if (r_waterstate.texturewidth)
5115         {
5116                 r_waterstate.enabled = true;
5117
5118                 // when doing a reduced render (HDR) we want to use a smaller area
5119                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5120                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5121
5122                 // set up variables that will be used in shader setup
5123                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5124                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5125                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5126                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5127         }
5128
5129         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5130         r_waterstate.numwaterplanes = 0;
5131 }
5132
5133 void R_Water_AddWaterPlane(msurface_t *surface)
5134 {
5135         int triangleindex, planeindex;
5136         const int *e;
5137         vec3_t vert[3];
5138         vec3_t normal;
5139         vec3_t center;
5140         mplane_t plane;
5141         r_waterstate_waterplane_t *p;
5142         texture_t *t = R_GetCurrentTexture(surface->texture);
5143         // just use the first triangle with a valid normal for any decisions
5144         VectorClear(normal);
5145         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5146         {
5147                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5148                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5149                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5150                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5151                 if (VectorLength2(normal) >= 0.001)
5152                         break;
5153         }
5154
5155         VectorCopy(normal, plane.normal);
5156         VectorNormalize(plane.normal);
5157         plane.dist = DotProduct(vert[0], plane.normal);
5158         PlaneClassify(&plane);
5159         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5160         {
5161                 // skip backfaces (except if nocullface is set)
5162                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5163                         return;
5164                 VectorNegate(plane.normal, plane.normal);
5165                 plane.dist *= -1;
5166                 PlaneClassify(&plane);
5167         }
5168
5169
5170         // find a matching plane if there is one
5171         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5172                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5173                         break;
5174         if (planeindex >= r_waterstate.maxwaterplanes)
5175                 return; // nothing we can do, out of planes
5176
5177         // if this triangle does not fit any known plane rendered this frame, add one
5178         if (planeindex >= r_waterstate.numwaterplanes)
5179         {
5180                 // store the new plane
5181                 r_waterstate.numwaterplanes++;
5182                 p->plane = plane;
5183                 // clear materialflags and pvs
5184                 p->materialflags = 0;
5185                 p->pvsvalid = false;
5186         }
5187         // merge this surface's materialflags into the waterplane
5188         p->materialflags |= t->currentmaterialflags;
5189         // merge this surface's PVS into the waterplane
5190         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5191         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5192          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5193         {
5194                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5195                 p->pvsvalid = true;
5196         }
5197 }
5198
5199 static void R_Water_ProcessPlanes(void)
5200 {
5201         r_refdef_view_t originalview;
5202         r_refdef_view_t myview;
5203         int planeindex;
5204         r_waterstate_waterplane_t *p;
5205
5206         originalview = r_refdef.view;
5207
5208         // make sure enough textures are allocated
5209         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5210         {
5211                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5212                 {
5213                         if (!p->texture_refraction)
5214                                 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);
5215                         if (!p->texture_refraction)
5216                                 goto error;
5217                 }
5218
5219                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5220                 {
5221                         if (!p->texture_reflection)
5222                                 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);
5223                         if (!p->texture_reflection)
5224                                 goto error;
5225                 }
5226         }
5227
5228         // render views
5229         r_refdef.view = originalview;
5230         r_refdef.view.showdebug = false;
5231         r_refdef.view.width = r_waterstate.waterwidth;
5232         r_refdef.view.height = r_waterstate.waterheight;
5233         r_refdef.view.useclipplane = true;
5234         myview = r_refdef.view;
5235         r_waterstate.renderingscene = true;
5236         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5237         {
5238                 // render the normal view scene and copy into texture
5239                 // (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)
5240                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5241                 {
5242                         r_refdef.view = myview;
5243                         r_refdef.view.clipplane = p->plane;
5244                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5245                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5246                         PlaneClassify(&r_refdef.view.clipplane);
5247
5248                         R_ResetViewRendering3D();
5249                         R_ClearScreen(r_refdef.fogenabled);
5250                         R_View_Update();
5251                         R_RenderScene();
5252
5253                         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);
5254                 }
5255
5256                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5257                 {
5258                         r_refdef.view = myview;
5259                         // render reflected scene and copy into texture
5260                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5261                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5262                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5263                         r_refdef.view.clipplane = p->plane;
5264                         // reverse the cullface settings for this render
5265                         r_refdef.view.cullface_front = GL_FRONT;
5266                         r_refdef.view.cullface_back = GL_BACK;
5267                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5268                         {
5269                                 r_refdef.view.usecustompvs = true;
5270                                 if (p->pvsvalid)
5271                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5272                                 else
5273                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5274                         }
5275
5276                         R_ResetViewRendering3D();
5277                         R_ClearScreen(r_refdef.fogenabled);
5278                         R_View_Update();
5279                         R_RenderScene();
5280
5281                         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);
5282                 }
5283         }
5284         r_waterstate.renderingscene = false;
5285         r_refdef.view = originalview;
5286         R_ResetViewRendering3D();
5287         R_ClearScreen(r_refdef.fogenabled);
5288         R_View_Update();
5289         return;
5290 error:
5291         r_refdef.view = originalview;
5292         r_waterstate.renderingscene = false;
5293         Cvar_SetValueQuick(&r_water, 0);
5294         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5295         return;
5296 }
5297
5298 void R_Bloom_StartFrame(void)
5299 {
5300         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5301
5302         switch(vid.renderpath)
5303         {
5304         case RENDERPATH_GL20:
5305         case RENDERPATH_CGGL:
5306                 break;
5307         case RENDERPATH_GL13:
5308         case RENDERPATH_GL11:
5309                 return;
5310         }
5311
5312         // set bloomwidth and bloomheight to the bloom resolution that will be
5313         // used (often less than the screen resolution for faster rendering)
5314         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5315         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5316         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5317         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5318         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5319
5320         // calculate desired texture sizes
5321         if (vid.support.arb_texture_non_power_of_two)
5322         {
5323                 screentexturewidth = r_refdef.view.width;
5324                 screentextureheight = r_refdef.view.height;
5325                 bloomtexturewidth = r_bloomstate.bloomwidth;
5326                 bloomtextureheight = r_bloomstate.bloomheight;
5327         }
5328         else
5329         {
5330                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5331                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5332                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5333                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5334         }
5335
5336         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))
5337         {
5338                 Cvar_SetValueQuick(&r_hdr, 0);
5339                 Cvar_SetValueQuick(&r_bloom, 0);
5340                 Cvar_SetValueQuick(&r_motionblur, 0);
5341                 Cvar_SetValueQuick(&r_damageblur, 0);
5342         }
5343
5344         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)))
5345                 screentexturewidth = screentextureheight = 0;
5346         if (!r_hdr.integer && !r_bloom.integer)
5347                 bloomtexturewidth = bloomtextureheight = 0;
5348
5349         // allocate textures as needed
5350         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5351         {
5352                 if (r_bloomstate.texture_screen)
5353                         R_FreeTexture(r_bloomstate.texture_screen);
5354                 r_bloomstate.texture_screen = NULL;
5355                 r_bloomstate.screentexturewidth = screentexturewidth;
5356                 r_bloomstate.screentextureheight = screentextureheight;
5357                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5358                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
5359         }
5360         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5361         {
5362                 if (r_bloomstate.texture_bloom)
5363                         R_FreeTexture(r_bloomstate.texture_bloom);
5364                 r_bloomstate.texture_bloom = NULL;
5365                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5366                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5367                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5368                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
5369         }
5370
5371         // when doing a reduced render (HDR) we want to use a smaller area
5372         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5373         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5374         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5375         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5376         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5377
5378         // set up a texcoord array for the full resolution screen image
5379         // (we have to keep this around to copy back during final render)
5380         r_bloomstate.screentexcoord2f[0] = 0;
5381         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5382         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5383         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5384         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5385         r_bloomstate.screentexcoord2f[5] = 0;
5386         r_bloomstate.screentexcoord2f[6] = 0;
5387         r_bloomstate.screentexcoord2f[7] = 0;
5388
5389         // set up a texcoord array for the reduced resolution bloom image
5390         // (which will be additive blended over the screen image)
5391         r_bloomstate.bloomtexcoord2f[0] = 0;
5392         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5393         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5394         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5395         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5396         r_bloomstate.bloomtexcoord2f[5] = 0;
5397         r_bloomstate.bloomtexcoord2f[6] = 0;
5398         r_bloomstate.bloomtexcoord2f[7] = 0;
5399
5400         if (r_hdr.integer || r_bloom.integer)
5401         {
5402                 r_bloomstate.enabled = true;
5403                 r_bloomstate.hdr = r_hdr.integer != 0;
5404         }
5405
5406         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);
5407 }
5408
5409 void R_Bloom_CopyBloomTexture(float colorscale)
5410 {
5411         r_refdef.stats.bloom++;
5412
5413         // scale down screen texture to the bloom texture size
5414         CHECKGLERROR
5415         R_SetViewport(&r_bloomstate.viewport);
5416         GL_BlendFunc(GL_ONE, GL_ZERO);
5417         GL_Color(colorscale, colorscale, colorscale, 1);
5418         // TODO: optimize with multitexture or GLSL
5419         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5420         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5421         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5422         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5423
5424         // we now have a bloom image in the framebuffer
5425         // copy it into the bloom image texture for later processing
5426         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);
5427         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5428 }
5429
5430 void R_Bloom_CopyHDRTexture(void)
5431 {
5432         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);
5433         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5434 }
5435
5436 void R_Bloom_MakeTexture(void)
5437 {
5438         int x, range, dir;
5439         float xoffset, yoffset, r, brighten;
5440
5441         r_refdef.stats.bloom++;
5442
5443         R_ResetViewRendering2D();
5444         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5445         R_Mesh_ColorPointer(NULL, 0, 0);
5446
5447         // we have a bloom image in the framebuffer
5448         CHECKGLERROR
5449         R_SetViewport(&r_bloomstate.viewport);
5450
5451         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5452         {
5453                 x *= 2;
5454                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5455                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5456                 GL_Color(r, r, r, 1);
5457                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5458                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5459                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5460                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5461
5462                 // copy the vertically blurred bloom view to a texture
5463                 GL_ActiveTexture(0);
5464                 CHECKGLERROR
5465                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
5466                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5467         }
5468
5469         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5470         brighten = r_bloom_brighten.value;
5471         if (r_hdr.integer)
5472                 brighten *= r_hdr_range.value;
5473         brighten = sqrt(brighten);
5474         if(range >= 1)
5475                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5476         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5477         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
5478
5479         for (dir = 0;dir < 2;dir++)
5480         {
5481                 // blend on at multiple vertical offsets to achieve a vertical blur
5482                 // TODO: do offset blends using GLSL
5483                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5484                 GL_BlendFunc(GL_ONE, GL_ZERO);
5485                 for (x = -range;x <= range;x++)
5486                 {
5487                         if (!dir){xoffset = 0;yoffset = x;}
5488                         else {xoffset = x;yoffset = 0;}
5489                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5490                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5491                         // compute a texcoord array with the specified x and y offset
5492                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5493                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5494                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5495                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5496                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5497                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5498                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5499                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5500                         // this r value looks like a 'dot' particle, fading sharply to
5501                         // black at the edges
5502                         // (probably not realistic but looks good enough)
5503                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5504                         //r = brighten/(range*2+1);
5505                         r = brighten / (range * 2 + 1);
5506                         if(range >= 1)
5507                                 r *= (1 - x*x/(float)(range*range));
5508                         GL_Color(r, r, r, 1);
5509                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5510                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5511                         GL_BlendFunc(GL_ONE, GL_ONE);
5512                 }
5513
5514                 // copy the vertically blurred bloom view to a texture
5515                 GL_ActiveTexture(0);
5516                 CHECKGLERROR
5517                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
5518                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5519         }
5520
5521         // apply subtract last
5522         // (just like it would be in a GLSL shader)
5523         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
5524         {
5525                 GL_BlendFunc(GL_ONE, GL_ZERO);
5526                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5527                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5528                 GL_Color(1, 1, 1, 1);
5529                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5530                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5531
5532                 GL_BlendFunc(GL_ONE, GL_ONE);
5533                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
5534                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5535                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5536                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
5537                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5538                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5539                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
5540
5541                 // copy the darkened bloom view to a texture
5542                 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);
5543                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5544         }
5545 }
5546
5547 void R_HDR_RenderBloomTexture(void)
5548 {
5549         int oldwidth, oldheight;
5550         float oldcolorscale;
5551
5552         oldcolorscale = r_refdef.view.colorscale;
5553         oldwidth = r_refdef.view.width;
5554         oldheight = r_refdef.view.height;
5555         r_refdef.view.width = r_bloomstate.bloomwidth;
5556         r_refdef.view.height = r_bloomstate.bloomheight;
5557
5558         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5559         // TODO: add exposure compensation features
5560         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5561
5562         r_refdef.view.showdebug = false;
5563         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5564
5565         R_ResetViewRendering3D();
5566
5567         R_ClearScreen(r_refdef.fogenabled);
5568         if (r_timereport_active)
5569                 R_TimeReport("HDRclear");
5570
5571         R_View_Update();
5572         if (r_timereport_active)
5573                 R_TimeReport("visibility");
5574
5575         // only do secondary renders with HDR if r_hdr is 2 or higher
5576         r_waterstate.numwaterplanes = 0;
5577         if (r_waterstate.enabled && r_hdr.integer >= 2)
5578                 R_RenderWaterPlanes();
5579
5580         r_refdef.view.showdebug = true;
5581         R_RenderScene();
5582         r_waterstate.numwaterplanes = 0;
5583
5584         R_ResetViewRendering2D();
5585
5586         R_Bloom_CopyHDRTexture();
5587         R_Bloom_MakeTexture();
5588
5589         // restore the view settings
5590         r_refdef.view.width = oldwidth;
5591         r_refdef.view.height = oldheight;
5592         r_refdef.view.colorscale = oldcolorscale;
5593         r_frame++; // used only by R_GetCurrentTexture
5594
5595         R_ResetViewRendering3D();
5596
5597         R_ClearScreen(r_refdef.fogenabled);
5598         if (r_timereport_active)
5599                 R_TimeReport("viewclear");
5600 }
5601
5602 static void R_BlendView(void)
5603 {
5604         unsigned int permutation;
5605         float uservecs[4][4];
5606
5607         switch (vid.renderpath)
5608         {
5609         case RENDERPATH_GL20:
5610         case RENDERPATH_CGGL:
5611                 permutation =
5612                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5613                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5614                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5615                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5616                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5617
5618                 if (r_bloomstate.texture_screen)
5619                 {
5620                         // make sure the buffer is available
5621                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5622
5623                         R_ResetViewRendering2D();
5624                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5625                         R_Mesh_ColorPointer(NULL, 0, 0);
5626
5627                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5628                         {
5629                                 // declare variables
5630                                 float speed;
5631                                 static float avgspeed;
5632
5633                                 speed = VectorLength(cl.movement_velocity);
5634
5635                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5636                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5637
5638                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5639                                 speed = bound(0, speed, 1);
5640                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5641
5642                                 // calculate values into a standard alpha
5643                                 cl.motionbluralpha = 1 - exp(-
5644                                                 (
5645                                                  (r_motionblur.value * speed / 80)
5646                                                  +
5647                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5648                                                 )
5649                                                 /
5650                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5651                                            );
5652
5653                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5654                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5655                                 // apply the blur
5656                                 if (cl.motionbluralpha > 0)
5657                                 {
5658                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5659                                         GL_Color(1, 1, 1, cl.motionbluralpha);
5660                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5661                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5662                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5663                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5664                                 }
5665                         }
5666
5667                         // copy view into the screen texture
5668                         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);
5669                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5670                 }
5671                 else if (!r_bloomstate.texture_bloom)
5672                 {
5673                         // we may still have to do view tint...
5674                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
5675                         {
5676                                 // apply a color tint to the whole view
5677                                 R_ResetViewRendering2D();
5678                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5679                                 R_Mesh_ColorPointer(NULL, 0, 0);
5680                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5681                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5682                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5683                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5684                         }
5685                         break; // no screen processing, no bloom, skip it
5686                 }
5687
5688                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
5689                 {
5690                         // render simple bloom effect
5691                         // copy the screen and shrink it and darken it for the bloom process
5692                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
5693                         // make the bloom texture
5694                         R_Bloom_MakeTexture();
5695                 }
5696
5697 #if _MSC_VER >= 1400
5698 #define sscanf sscanf_s
5699 #endif
5700                 memset(uservecs, 0, sizeof(uservecs));
5701                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
5702                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
5703                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
5704                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
5705
5706                 R_ResetViewRendering2D();
5707                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5708                 R_Mesh_ColorPointer(NULL, 0, 0);
5709                 GL_Color(1, 1, 1, 1);
5710                 GL_BlendFunc(GL_ONE, GL_ZERO);
5711                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5712                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5713
5714                 switch(vid.renderpath)
5715                 {
5716                 case RENDERPATH_GL20:
5717                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
5718                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , R_GetTexture(r_bloomstate.texture_screen));
5719                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , R_GetTexture(r_bloomstate.texture_bloom ));
5720                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps       ));
5721                         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]);
5722                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
5723                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
5724                         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]);
5725                         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]);
5726                         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]);
5727                         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]);
5728                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
5729                         break;
5730                 case RENDERPATH_CGGL:
5731 #ifdef SUPPORTCG
5732                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
5733                         if (r_cg_permutation->fp_Texture_First     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First     , R_GetTexture(r_bloomstate.texture_screen));
5734                         if (r_cg_permutation->fp_Texture_Second    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second    , R_GetTexture(r_bloomstate.texture_bloom ));
5735                         if (r_cg_permutation->fp_Texture_GammaRamps) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_GammaRamps, R_GetTexture(r_texture_gammaramps       ));
5736                         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]);
5737                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);
5738                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
5739                         if (r_cg_permutation->fp_UserVec1          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
5740                         if (r_cg_permutation->fp_UserVec2          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
5741                         if (r_cg_permutation->fp_UserVec3          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
5742                         if (r_cg_permutation->fp_UserVec4          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
5743                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);
5744 #endif
5745                         break;
5746                 default:
5747                         break;
5748                 }
5749                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5750                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5751                 break;
5752         case RENDERPATH_GL13:
5753         case RENDERPATH_GL11:
5754                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
5755                 {
5756                         // apply a color tint to the whole view
5757                         R_ResetViewRendering2D();
5758                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5759                         R_Mesh_ColorPointer(NULL, 0, 0);
5760                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5761                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5762                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5763                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5764                 }
5765                 break;
5766         }
5767 }
5768
5769 matrix4x4_t r_waterscrollmatrix;
5770
5771 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
5772 {
5773         if (r_refdef.fog_density)
5774         {
5775                 r_refdef.fogcolor[0] = r_refdef.fog_red;
5776                 r_refdef.fogcolor[1] = r_refdef.fog_green;
5777                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5778
5779                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5780                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5781                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5782                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5783
5784                 {
5785                         vec3_t fogvec;
5786                         VectorCopy(r_refdef.fogcolor, fogvec);
5787                         //   color.rgb *= ContrastBoost * SceneBrightness;
5788                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5789                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5790                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5791                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5792                 }
5793         }
5794 }
5795
5796 void R_UpdateVariables(void)
5797 {
5798         R_Textures_Frame();
5799
5800         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
5801
5802         r_refdef.farclip = r_farclip_base.value;
5803         if (r_refdef.scene.worldmodel)
5804                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5805         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5806
5807         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5808                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5809         r_refdef.polygonfactor = 0;
5810         r_refdef.polygonoffset = 0;
5811         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5812         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5813
5814         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5815         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5816         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5817         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5818         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5819         if (r_showsurfaces.integer)
5820         {
5821                 r_refdef.scene.rtworld = false;
5822                 r_refdef.scene.rtworldshadows = false;
5823                 r_refdef.scene.rtdlight = false;
5824                 r_refdef.scene.rtdlightshadows = false;
5825                 r_refdef.lightmapintensity = 0;
5826         }
5827
5828         if (gamemode == GAME_NEHAHRA)
5829         {
5830                 if (gl_fogenable.integer)
5831                 {
5832                         r_refdef.oldgl_fogenable = true;
5833                         r_refdef.fog_density = gl_fogdensity.value;
5834                         r_refdef.fog_red = gl_fogred.value;
5835                         r_refdef.fog_green = gl_foggreen.value;
5836                         r_refdef.fog_blue = gl_fogblue.value;
5837                         r_refdef.fog_alpha = 1;
5838                         r_refdef.fog_start = 0;
5839                         r_refdef.fog_end = gl_skyclip.value;
5840                         r_refdef.fog_height = 1<<30;
5841                         r_refdef.fog_fadedepth = 128;
5842                 }
5843                 else if (r_refdef.oldgl_fogenable)
5844                 {
5845                         r_refdef.oldgl_fogenable = false;
5846                         r_refdef.fog_density = 0;
5847                         r_refdef.fog_red = 0;
5848                         r_refdef.fog_green = 0;
5849                         r_refdef.fog_blue = 0;
5850                         r_refdef.fog_alpha = 0;
5851                         r_refdef.fog_start = 0;
5852                         r_refdef.fog_end = 0;
5853                         r_refdef.fog_height = 1<<30;
5854                         r_refdef.fog_fadedepth = 128;
5855                 }
5856         }
5857
5858         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5859         r_refdef.fog_start = max(0, r_refdef.fog_start);
5860         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5861
5862         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5863
5864         if (r_refdef.fog_density && r_drawfog.integer)
5865         {
5866                 r_refdef.fogenabled = true;
5867                 // this is the point where the fog reaches 0.9986 alpha, which we
5868                 // consider a good enough cutoff point for the texture
5869                 // (0.9986 * 256 == 255.6)
5870                 if (r_fog_exp2.integer)
5871                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5872                 else
5873                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5874                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5875                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5876                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5877                 // fog color was already set
5878                 // update the fog texture
5879                 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)
5880                         R_BuildFogTexture();
5881         }
5882         else
5883                 r_refdef.fogenabled = false;
5884
5885         switch(vid.renderpath)
5886         {
5887         case RENDERPATH_GL20:
5888         case RENDERPATH_CGGL:
5889                 if(v_glslgamma.integer && !vid_gammatables_trivial)
5890                 {
5891                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5892                         {
5893                                 // build GLSL gamma texture
5894 #define RAMPWIDTH 256
5895                                 unsigned short ramp[RAMPWIDTH * 3];
5896                                 unsigned char rampbgr[RAMPWIDTH][4];
5897                                 int i;
5898
5899                                 r_texture_gammaramps_serial = vid_gammatables_serial;
5900
5901                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5902                                 for(i = 0; i < RAMPWIDTH; ++i)
5903                                 {
5904                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5905                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5906                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5907                                         rampbgr[i][3] = 0;
5908                                 }
5909                                 if (r_texture_gammaramps)
5910                                 {
5911                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5912                                 }
5913                                 else
5914                                 {
5915                                         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);
5916                                 }
5917                         }
5918                 }
5919                 else
5920                 {
5921                         // remove GLSL gamma texture
5922                 }
5923                 break;
5924         case RENDERPATH_GL13:
5925         case RENDERPATH_GL11:
5926                 break;
5927         }
5928 }
5929
5930 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5931 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5932 /*
5933 ================
5934 R_SelectScene
5935 ================
5936 */
5937 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5938         if( scenetype != r_currentscenetype ) {
5939                 // store the old scenetype
5940                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5941                 r_currentscenetype = scenetype;
5942                 // move in the new scene
5943                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5944         }
5945 }
5946
5947 /*
5948 ================
5949 R_GetScenePointer
5950 ================
5951 */
5952 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5953 {
5954         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5955         if( scenetype == r_currentscenetype ) {
5956                 return &r_refdef.scene;
5957         } else {
5958                 return &r_scenes_store[ scenetype ];
5959         }
5960 }
5961
5962 /*
5963 ================
5964 R_RenderView
5965 ================
5966 */
5967 void R_RenderView(void)
5968 {
5969         if (r_timereport_active)
5970                 R_TimeReport("start");
5971         r_frame++; // used only by R_GetCurrentTexture
5972         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5973
5974         if (!r_drawentities.integer)
5975                 r_refdef.scene.numentities = 0;
5976
5977         R_AnimCache_ClearCache();
5978         R_FrameData_NewFrame();
5979
5980         if (r_refdef.view.isoverlay)
5981         {
5982                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5983                 GL_Clear( GL_DEPTH_BUFFER_BIT );
5984                 R_TimeReport("depthclear");
5985
5986                 r_refdef.view.showdebug = false;
5987
5988                 r_waterstate.enabled = false;
5989                 r_waterstate.numwaterplanes = 0;
5990
5991                 R_RenderScene();
5992
5993                 CHECKGLERROR
5994                 return;
5995         }
5996
5997         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
5998                 return; //Host_Error ("R_RenderView: NULL worldmodel");
5999
6000         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
6001
6002         // break apart the view matrix into vectors for various purposes
6003         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
6004         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
6005         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
6006         VectorNegate(r_refdef.view.left, r_refdef.view.right);
6007         // make an inverted copy of the view matrix for tracking sprites
6008         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
6009
6010         R_Shadow_UpdateWorldLightSelection();
6011
6012         R_Bloom_StartFrame();
6013         R_Water_StartFrame();
6014
6015         CHECKGLERROR
6016         if (r_timereport_active)
6017                 R_TimeReport("viewsetup");
6018
6019         R_ResetViewRendering3D();
6020
6021         if (r_refdef.view.clear || r_refdef.fogenabled)
6022         {
6023                 R_ClearScreen(r_refdef.fogenabled);
6024                 if (r_timereport_active)
6025                         R_TimeReport("viewclear");
6026         }
6027         r_refdef.view.clear = true;
6028
6029         // this produces a bloom texture to be used in R_BlendView() later
6030         if (r_hdr.integer && r_bloomstate.bloomwidth)
6031                 R_HDR_RenderBloomTexture();
6032
6033         r_refdef.view.showdebug = true;
6034
6035         R_View_Update();
6036         if (r_timereport_active)
6037                 R_TimeReport("visibility");
6038
6039         r_waterstate.numwaterplanes = 0;
6040         if (r_waterstate.enabled)
6041                 R_RenderWaterPlanes();
6042
6043         R_RenderScene();
6044         r_waterstate.numwaterplanes = 0;
6045
6046         R_BlendView();
6047         if (r_timereport_active)
6048                 R_TimeReport("blendview");
6049
6050         GL_Scissor(0, 0, vid.width, vid.height);
6051         GL_ScissorTest(false);
6052         CHECKGLERROR
6053 }
6054
6055 void R_RenderWaterPlanes(void)
6056 {
6057         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6058         {
6059                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6060                 if (r_timereport_active)
6061                         R_TimeReport("waterworld");
6062         }
6063
6064         // don't let sound skip if going slow
6065         if (r_refdef.scene.extraupdate)
6066                 S_ExtraUpdate ();
6067
6068         R_DrawModelsAddWaterPlanes();
6069         if (r_timereport_active)
6070                 R_TimeReport("watermodels");
6071
6072         if (r_waterstate.numwaterplanes)
6073         {
6074                 R_Water_ProcessPlanes();
6075                 if (r_timereport_active)
6076                         R_TimeReport("waterscenes");
6077         }
6078 }
6079
6080 extern void R_DrawLightningBeams (void);
6081 extern void VM_CL_AddPolygonsToMeshQueue (void);
6082 extern void R_DrawPortals (void);
6083 extern cvar_t cl_locs_show;
6084 static void R_DrawLocs(void);
6085 static void R_DrawEntityBBoxes(void);
6086 static void R_DrawModelDecals(void);
6087 extern cvar_t cl_decals_newsystem;
6088 extern qboolean r_shadow_usingdeferredprepass;
6089 void R_RenderScene(void)
6090 {
6091         r_refdef.stats.renders++;
6092
6093         R_UpdateFogColor();
6094
6095         // don't let sound skip if going slow
6096         if (r_refdef.scene.extraupdate)
6097                 S_ExtraUpdate ();
6098
6099         R_MeshQueue_BeginScene();
6100
6101         R_SkyStartFrame();
6102
6103         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);
6104
6105         if (cl.csqc_vidvars.drawworld)
6106         {
6107                 // don't let sound skip if going slow
6108                 if (r_refdef.scene.extraupdate)
6109                         S_ExtraUpdate ();
6110
6111                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6112                 {
6113                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6114                         if (r_timereport_active)
6115                                 R_TimeReport("worldsky");
6116                 }
6117
6118                 if (R_DrawBrushModelsSky() && r_timereport_active)
6119                         R_TimeReport("bmodelsky");
6120
6121                 if (skyrendermasked && skyrenderlater)
6122                 {
6123                         // we have to force off the water clipping plane while rendering sky
6124                         R_SetupView(false);
6125                         R_Sky();
6126                         R_SetupView(true);
6127                         if (r_timereport_active)
6128                                 R_TimeReport("sky");
6129                 }
6130         }
6131
6132         R_AnimCache_CacheVisibleEntities();
6133         if (r_timereport_active)
6134                 R_TimeReport("animation");
6135
6136         R_Shadow_PrepareLights();
6137         if (r_timereport_active)
6138                 R_TimeReport("preparelights");
6139
6140         if (r_shadow_usingdeferredprepass)
6141                 R_Shadow_DrawPrepass();
6142
6143         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6144         {
6145                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6146                 if (r_timereport_active)
6147                         R_TimeReport("worlddepth");
6148         }
6149         if (r_depthfirst.integer >= 2)
6150         {
6151                 R_DrawModelsDepth();
6152                 if (r_timereport_active)
6153                         R_TimeReport("modeldepth");
6154         }
6155
6156         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6157         {
6158                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6159                 if (r_timereport_active)
6160                         R_TimeReport("world");
6161         }
6162
6163         // don't let sound skip if going slow
6164         if (r_refdef.scene.extraupdate)
6165                 S_ExtraUpdate ();
6166
6167         R_DrawModels();
6168         if (r_timereport_active)
6169                 R_TimeReport("models");
6170
6171         // don't let sound skip if going slow
6172         if (r_refdef.scene.extraupdate)
6173                 S_ExtraUpdate ();
6174
6175         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6176         {
6177                 R_DrawModelShadows();
6178                 R_ResetViewRendering3D();
6179                 // don't let sound skip if going slow
6180                 if (r_refdef.scene.extraupdate)
6181                         S_ExtraUpdate ();
6182         }
6183
6184         if (!r_shadow_usingdeferredprepass)
6185         {
6186                 R_Shadow_DrawLights();
6187                 if (r_timereport_active)
6188                         R_TimeReport("rtlights");
6189         }
6190
6191         // don't let sound skip if going slow
6192         if (r_refdef.scene.extraupdate)
6193                 S_ExtraUpdate ();
6194
6195         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6196         {
6197                 R_DrawModelShadows();
6198                 R_ResetViewRendering3D();
6199                 // don't let sound skip if going slow
6200                 if (r_refdef.scene.extraupdate)
6201                         S_ExtraUpdate ();
6202         }
6203
6204         if (cl.csqc_vidvars.drawworld)
6205         {
6206                 if (cl_decals_newsystem.integer)
6207                 {
6208                         R_DrawModelDecals();
6209                         if (r_timereport_active)
6210                                 R_TimeReport("modeldecals");
6211                 }
6212                 else
6213                 {
6214                         R_DrawDecals();
6215                         if (r_timereport_active)
6216                                 R_TimeReport("decals");
6217                 }
6218
6219                 R_DrawParticles();
6220                 if (r_timereport_active)
6221                         R_TimeReport("particles");
6222
6223                 R_DrawExplosions();
6224                 if (r_timereport_active)
6225                         R_TimeReport("explosions");
6226
6227                 R_DrawLightningBeams();
6228                 if (r_timereport_active)
6229                         R_TimeReport("lightning");
6230         }
6231
6232         VM_CL_AddPolygonsToMeshQueue();
6233
6234         if (r_refdef.view.showdebug)
6235         {
6236                 if (cl_locs_show.integer)
6237                 {
6238                         R_DrawLocs();
6239                         if (r_timereport_active)
6240                                 R_TimeReport("showlocs");
6241                 }
6242
6243                 if (r_drawportals.integer)
6244                 {
6245                         R_DrawPortals();
6246                         if (r_timereport_active)
6247                                 R_TimeReport("portals");
6248                 }
6249
6250                 if (r_showbboxes.value > 0)
6251                 {
6252                         R_DrawEntityBBoxes();
6253                         if (r_timereport_active)
6254                                 R_TimeReport("bboxes");
6255                 }
6256         }
6257
6258         R_MeshQueue_RenderTransparent();
6259         if (r_timereport_active)
6260                 R_TimeReport("drawtrans");
6261
6262         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))
6263         {
6264                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6265                 if (r_timereport_active)
6266                         R_TimeReport("worlddebug");
6267                 R_DrawModelsDebug();
6268                 if (r_timereport_active)
6269                         R_TimeReport("modeldebug");
6270         }
6271
6272         if (cl.csqc_vidvars.drawworld)
6273         {
6274                 R_Shadow_DrawCoronas();
6275                 if (r_timereport_active)
6276                         R_TimeReport("coronas");
6277         }
6278
6279         // don't let sound skip if going slow
6280         if (r_refdef.scene.extraupdate)
6281                 S_ExtraUpdate ();
6282
6283         R_ResetViewRendering2D();
6284 }
6285
6286 static const unsigned short bboxelements[36] =
6287 {
6288         5, 1, 3, 5, 3, 7,
6289         6, 2, 0, 6, 0, 4,
6290         7, 3, 2, 7, 2, 6,
6291         4, 0, 1, 4, 1, 5,
6292         4, 5, 7, 4, 7, 6,
6293         1, 0, 2, 1, 2, 3,
6294 };
6295
6296 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6297 {
6298         int i;
6299         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6300
6301         RSurf_ActiveWorldEntity();
6302
6303         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6304         GL_DepthMask(false);
6305         GL_DepthRange(0, 1);
6306         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6307         R_Mesh_ResetTextureState();
6308
6309         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6310         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6311         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6312         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6313         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6314         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6315         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6316         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6317         R_FillColors(color4f, 8, cr, cg, cb, ca);
6318         if (r_refdef.fogenabled)
6319         {
6320                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6321                 {
6322                         f1 = RSurf_FogVertex(v);
6323                         f2 = 1 - f1;
6324                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6325                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6326                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6327                 }
6328         }
6329         R_Mesh_VertexPointer(vertex3f, 0, 0);
6330         R_Mesh_ColorPointer(color4f, 0, 0);
6331         R_Mesh_ResetTextureState();
6332         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6333         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
6334 }
6335
6336 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6337 {
6338         int i;
6339         float color[4];
6340         prvm_edict_t *edict;
6341         prvm_prog_t *prog_save = prog;
6342
6343         // this function draws bounding boxes of server entities
6344         if (!sv.active)
6345                 return;
6346
6347         GL_CullFace(GL_NONE);
6348         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6349
6350         prog = 0;
6351         SV_VM_Begin();
6352         for (i = 0;i < numsurfaces;i++)
6353         {
6354                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6355                 switch ((int)edict->fields.server->solid)
6356                 {
6357                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6358                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6359                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6360                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6361                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6362                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6363                 }
6364                 color[3] *= r_showbboxes.value;
6365                 color[3] = bound(0, color[3], 1);
6366                 GL_DepthTest(!r_showdisabledepthtest.integer);
6367                 GL_CullFace(r_refdef.view.cullface_front);
6368                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6369         }
6370         SV_VM_End();
6371         prog = prog_save;
6372 }
6373
6374 static void R_DrawEntityBBoxes(void)
6375 {
6376         int i;
6377         prvm_edict_t *edict;
6378         vec3_t center;
6379         prvm_prog_t *prog_save = prog;
6380
6381         // this function draws bounding boxes of server entities
6382         if (!sv.active)
6383                 return;
6384
6385         prog = 0;
6386         SV_VM_Begin();
6387         for (i = 0;i < prog->num_edicts;i++)
6388         {
6389                 edict = PRVM_EDICT_NUM(i);
6390                 if (edict->priv.server->free)
6391                         continue;
6392                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6393                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6394                         continue;
6395                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6396                         continue;
6397                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6398                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6399         }
6400         SV_VM_End();
6401         prog = prog_save;
6402 }
6403
6404 static const int nomodelelement3i[24] =
6405 {
6406         5, 2, 0,
6407         5, 1, 2,
6408         5, 0, 3,
6409         5, 3, 1,
6410         0, 2, 4,
6411         2, 1, 4,
6412         3, 0, 4,
6413         1, 3, 4
6414 };
6415
6416 static const unsigned short nomodelelement3s[24] =
6417 {
6418         5, 2, 0,
6419         5, 1, 2,
6420         5, 0, 3,
6421         5, 3, 1,
6422         0, 2, 4,
6423         2, 1, 4,
6424         3, 0, 4,
6425         1, 3, 4
6426 };
6427
6428 static const float nomodelvertex3f[6*3] =
6429 {
6430         -16,   0,   0,
6431          16,   0,   0,
6432           0, -16,   0,
6433           0,  16,   0,
6434           0,   0, -16,
6435           0,   0,  16
6436 };
6437
6438 static const float nomodelcolor4f[6*4] =
6439 {
6440         0.0f, 0.0f, 0.5f, 1.0f,
6441         0.0f, 0.0f, 0.5f, 1.0f,
6442         0.0f, 0.5f, 0.0f, 1.0f,
6443         0.0f, 0.5f, 0.0f, 1.0f,
6444         0.5f, 0.0f, 0.0f, 1.0f,
6445         0.5f, 0.0f, 0.0f, 1.0f
6446 };
6447
6448 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6449 {
6450         int i;
6451         float f1, f2, *c;
6452         float color4f[6*4];
6453
6454         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);
6455
6456         // this is only called once per entity so numsurfaces is always 1, and
6457         // surfacelist is always {0}, so this code does not handle batches
6458
6459         if (rsurface.ent_flags & RENDER_ADDITIVE)
6460         {
6461                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6462                 GL_DepthMask(false);
6463         }
6464         else if (rsurface.colormod[3] < 1)
6465         {
6466                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6467                 GL_DepthMask(false);
6468         }
6469         else
6470         {
6471                 GL_BlendFunc(GL_ONE, GL_ZERO);
6472                 GL_DepthMask(true);
6473         }
6474         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6475         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6476         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6477         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6478         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6479         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6480         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6481         R_Mesh_ColorPointer(color4f, 0, 0);
6482         for (i = 0, c = color4f;i < 6;i++, c += 4)
6483         {
6484                 c[0] *= rsurface.colormod[0];
6485                 c[1] *= rsurface.colormod[1];
6486                 c[2] *= rsurface.colormod[2];
6487                 c[3] *= rsurface.colormod[3];
6488         }
6489         if (r_refdef.fogenabled)
6490         {
6491                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6492                 {
6493                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
6494                         f2 = 1 - f1;
6495                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6496                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6497                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6498                 }
6499         }
6500         R_Mesh_ResetTextureState();
6501         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
6502 }
6503
6504 void R_DrawNoModel(entity_render_t *ent)
6505 {
6506         vec3_t org;
6507         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6508         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6509                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6510         else
6511                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6512 }
6513
6514 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6515 {
6516         vec3_t right1, right2, diff, normal;
6517
6518         VectorSubtract (org2, org1, normal);
6519
6520         // calculate 'right' vector for start
6521         VectorSubtract (r_refdef.view.origin, org1, diff);
6522         CrossProduct (normal, diff, right1);
6523         VectorNormalize (right1);
6524
6525         // calculate 'right' vector for end
6526         VectorSubtract (r_refdef.view.origin, org2, diff);
6527         CrossProduct (normal, diff, right2);
6528         VectorNormalize (right2);
6529
6530         vert[ 0] = org1[0] + width * right1[0];
6531         vert[ 1] = org1[1] + width * right1[1];
6532         vert[ 2] = org1[2] + width * right1[2];
6533         vert[ 3] = org1[0] - width * right1[0];
6534         vert[ 4] = org1[1] - width * right1[1];
6535         vert[ 5] = org1[2] - width * right1[2];
6536         vert[ 6] = org2[0] - width * right2[0];
6537         vert[ 7] = org2[1] - width * right2[1];
6538         vert[ 8] = org2[2] - width * right2[2];
6539         vert[ 9] = org2[0] + width * right2[0];
6540         vert[10] = org2[1] + width * right2[1];
6541         vert[11] = org2[2] + width * right2[2];
6542 }
6543
6544 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)
6545 {
6546         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6547         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6548         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6549         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6550         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6551         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6552         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6553         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6554         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6555         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6556         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6557         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
6558 }
6559
6560 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
6561 {
6562         int i;
6563         float *vertex3f;
6564         float v[3];
6565         VectorSet(v, x, y, z);
6566         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
6567                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
6568                         break;
6569         if (i == mesh->numvertices)
6570         {
6571                 if (mesh->numvertices < mesh->maxvertices)
6572                 {
6573                         VectorCopy(v, vertex3f);
6574                         mesh->numvertices++;
6575                 }
6576                 return mesh->numvertices;
6577         }
6578         else
6579                 return i;
6580 }
6581
6582 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
6583 {
6584         int i;
6585         int *e, element[3];
6586         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6587         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6588         e = mesh->element3i + mesh->numtriangles * 3;
6589         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
6590         {
6591                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
6592                 if (mesh->numtriangles < mesh->maxtriangles)
6593                 {
6594                         *e++ = element[0];
6595                         *e++ = element[1];
6596                         *e++ = element[2];
6597                         mesh->numtriangles++;
6598                 }
6599                 element[1] = element[2];
6600         }
6601 }
6602
6603 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
6604 {
6605         int i;
6606         int *e, element[3];
6607         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6608         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6609         e = mesh->element3i + mesh->numtriangles * 3;
6610         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
6611         {
6612                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
6613                 if (mesh->numtriangles < mesh->maxtriangles)
6614                 {
6615                         *e++ = element[0];
6616                         *e++ = element[1];
6617                         *e++ = element[2];
6618                         mesh->numtriangles++;
6619                 }
6620                 element[1] = element[2];
6621         }
6622 }
6623
6624 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
6625 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
6626 {
6627         int planenum, planenum2;
6628         int w;
6629         int tempnumpoints;
6630         mplane_t *plane, *plane2;
6631         double maxdist;
6632         double temppoints[2][256*3];
6633         // figure out how large a bounding box we need to properly compute this brush
6634         maxdist = 0;
6635         for (w = 0;w < numplanes;w++)
6636                 maxdist = max(maxdist, fabs(planes[w].dist));
6637         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
6638         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
6639         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
6640         {
6641                 w = 0;
6642                 tempnumpoints = 4;
6643                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
6644                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
6645                 {
6646                         if (planenum2 == planenum)
6647                                 continue;
6648                         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);
6649                         w = !w;
6650                 }
6651                 if (tempnumpoints < 3)
6652                         continue;
6653                 // generate elements forming a triangle fan for this polygon
6654                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
6655         }
6656 }
6657
6658 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)
6659 {
6660         texturelayer_t *layer;
6661         layer = t->currentlayers + t->currentnumlayers++;
6662         layer->type = type;
6663         layer->depthmask = depthmask;
6664         layer->blendfunc1 = blendfunc1;
6665         layer->blendfunc2 = blendfunc2;
6666         layer->texture = texture;
6667         layer->texmatrix = *matrix;
6668         layer->color[0] = r;
6669         layer->color[1] = g;
6670         layer->color[2] = b;
6671         layer->color[3] = a;
6672 }
6673
6674 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
6675 {
6676         double index, f;
6677         index = parms[2] + r_refdef.scene.time * parms[3];
6678         index -= floor(index);
6679         switch (func)
6680         {
6681         default:
6682         case Q3WAVEFUNC_NONE:
6683         case Q3WAVEFUNC_NOISE:
6684         case Q3WAVEFUNC_COUNT:
6685                 f = 0;
6686                 break;
6687         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
6688         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
6689         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
6690         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
6691         case Q3WAVEFUNC_TRIANGLE:
6692                 index *= 4;
6693                 f = index - floor(index);
6694                 if (index < 1)
6695                         f = f;
6696                 else if (index < 2)
6697                         f = 1 - f;
6698                 else if (index < 3)
6699                         f = -f;
6700                 else
6701                         f = -(1 - f);
6702                 break;
6703         }
6704         return (float)(parms[0] + parms[1] * f);
6705 }
6706
6707 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
6708 {
6709         int w, h, idx;
6710         float f;
6711         float tcmat[12];
6712         matrix4x4_t matrix, temp;
6713         switch(tcmod->tcmod)
6714         {
6715                 case Q3TCMOD_COUNT:
6716                 case Q3TCMOD_NONE:
6717                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6718                                 matrix = r_waterscrollmatrix;
6719                         else
6720                                 matrix = identitymatrix;
6721                         break;
6722                 case Q3TCMOD_ENTITYTRANSLATE:
6723                         // this is used in Q3 to allow the gamecode to control texcoord
6724                         // scrolling on the entity, which is not supported in darkplaces yet.
6725                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
6726                         break;
6727                 case Q3TCMOD_ROTATE:
6728                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
6729                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
6730                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
6731                         break;
6732                 case Q3TCMOD_SCALE:
6733                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
6734                         break;
6735                 case Q3TCMOD_SCROLL:
6736                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
6737                         break;
6738                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
6739                         w = (int) tcmod->parms[0];
6740                         h = (int) tcmod->parms[1];
6741                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
6742                         f = f - floor(f);
6743                         idx = (int) floor(f * w * h);
6744                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
6745                         break;
6746                 case Q3TCMOD_STRETCH:
6747                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
6748                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
6749                         break;
6750                 case Q3TCMOD_TRANSFORM:
6751                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
6752                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
6753                         VectorSet(tcmat +  6, 0                   , 0                , 1);
6754                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
6755                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
6756                         break;
6757                 case Q3TCMOD_TURBULENT:
6758                         // this is handled in the RSurf_PrepareVertices function
6759                         matrix = identitymatrix;
6760                         break;
6761         }
6762         temp = *texmatrix;
6763         Matrix4x4_Concat(texmatrix, &matrix, &temp);
6764 }
6765
6766 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
6767 {
6768         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
6769         char name[MAX_QPATH];
6770         skinframe_t *skinframe;
6771         unsigned char pixels[296*194];
6772         strlcpy(cache->name, skinname, sizeof(cache->name));
6773         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6774         if (developer_loading.integer)
6775                 Con_Printf("loading %s\n", name);
6776         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6777         if (!skinframe || !skinframe->base)
6778         {
6779                 unsigned char *f;
6780                 fs_offset_t filesize;
6781                 skinframe = NULL;
6782                 f = FS_LoadFile(name, tempmempool, true, &filesize);
6783                 if (f)
6784                 {
6785                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
6786                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6787                         Mem_Free(f);
6788                 }
6789         }
6790         cache->skinframe = skinframe;
6791 }
6792
6793 texture_t *R_GetCurrentTexture(texture_t *t)
6794 {
6795         int i;
6796         const entity_render_t *ent = rsurface.entity;
6797         dp_model_t *model = ent->model;
6798         q3shaderinfo_layer_tcmod_t *tcmod;
6799
6800         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
6801                 return t->currentframe;
6802         t->update_lastrenderframe = r_frame;
6803         t->update_lastrenderentity = (void *)ent;
6804
6805         // switch to an alternate material if this is a q1bsp animated material
6806         {
6807                 texture_t *texture = t;
6808                 int s = rsurface.ent_skinnum;
6809                 if ((unsigned int)s >= (unsigned int)model->numskins)
6810                         s = 0;
6811                 if (model->skinscenes)
6812                 {
6813                         if (model->skinscenes[s].framecount > 1)
6814                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6815                         else
6816                                 s = model->skinscenes[s].firstframe;
6817                 }
6818                 if (s > 0)
6819                         t = t + s * model->num_surfaces;
6820                 if (t->animated)
6821                 {
6822                         // use an alternate animation if the entity's frame is not 0,
6823                         // and only if the texture has an alternate animation
6824                         if (rsurface.ent_alttextures && t->anim_total[1])
6825                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6826                         else
6827                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6828                 }
6829                 texture->currentframe = t;
6830         }
6831
6832         // update currentskinframe to be a qw skin or animation frame
6833         if (rsurface.ent_qwskin >= 0)
6834         {
6835                 i = rsurface.ent_qwskin;
6836                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6837                 {
6838                         r_qwskincache_size = cl.maxclients;
6839                         if (r_qwskincache)
6840                                 Mem_Free(r_qwskincache);
6841                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6842                 }
6843                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6844                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6845                 t->currentskinframe = r_qwskincache[i].skinframe;
6846                 if (t->currentskinframe == NULL)
6847                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6848         }
6849         else if (t->numskinframes >= 2)
6850                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6851         if (t->backgroundnumskinframes >= 2)
6852                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6853
6854         t->currentmaterialflags = t->basematerialflags;
6855         t->currentalpha = rsurface.colormod[3];
6856         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6857                 t->currentalpha *= r_wateralpha.value;
6858         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6859                 t->currentalpha *= t->r_water_wateralpha;
6860         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6861                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6862         if (!(rsurface.ent_flags & RENDER_LIGHT))
6863                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6864         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6865         {
6866                 // pick a model lighting mode
6867                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6868                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6869                 else
6870                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6871         }
6872         if (rsurface.ent_flags & RENDER_ADDITIVE)
6873                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6874         else if (t->currentalpha < 1)
6875                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6876         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6877                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6878         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6879                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6880         if (t->backgroundnumskinframes)
6881                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6882         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6883         {
6884                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6885                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6886         }
6887         else
6888                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6889         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6890                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6891
6892         // there is no tcmod
6893         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6894         {
6895                 t->currenttexmatrix = r_waterscrollmatrix;
6896                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6897         }
6898         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6899         {
6900                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6901                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6902         }
6903
6904         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6905                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6906         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6907                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6908
6909         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6910         if (t->currentskinframe->qpixels)
6911                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6912         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6913         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
6914         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
6915         t->nmaptexture = t->currentskinframe->nmap;
6916         t->glosstexture = r_texture_black;
6917         t->glowtexture = t->currentskinframe->glow;
6918         t->fogtexture = t->currentskinframe->fog;
6919         if (t->backgroundnumskinframes)
6920         {
6921                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
6922                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
6923                 t->backgroundglosstexture = r_texture_black;
6924                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
6925         }
6926         else
6927         {
6928                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6929                 t->backgroundnmaptexture = r_texture_blanknormalmap;
6930                 t->backgroundglosstexture = r_texture_black;
6931                 t->backgroundglowtexture = NULL;
6932         }
6933         t->specularpower = r_shadow_glossexponent.value;
6934         // TODO: store reference values for these in the texture?
6935         t->specularscale = 0;
6936         if (r_shadow_gloss.integer > 0)
6937         {
6938                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6939                 {
6940                         if (r_shadow_glossintensity.value > 0)
6941                         {
6942                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6943                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6944                                 t->specularscale = r_shadow_glossintensity.value;
6945                         }
6946                 }
6947                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6948                 {
6949                         t->glosstexture = r_texture_white;
6950                         t->backgroundglosstexture = r_texture_white;
6951                         t->specularscale = r_shadow_gloss2intensity.value;
6952                         t->specularpower = r_shadow_gloss2exponent.value;
6953                 }
6954         }
6955         t->specularscale *= t->specularscalemod;
6956         t->specularpower *= t->specularpowermod;
6957
6958         // lightmaps mode looks bad with dlights using actual texturing, so turn
6959         // off the colormap and glossmap, but leave the normalmap on as it still
6960         // accurately represents the shading involved
6961         if (gl_lightmaps.integer)
6962         {
6963                 t->basetexture = r_texture_grey128;
6964                 t->pantstexture = r_texture_black;
6965                 t->shirttexture = r_texture_black;
6966                 t->nmaptexture = r_texture_blanknormalmap;
6967                 t->glosstexture = r_texture_black;
6968                 t->glowtexture = NULL;
6969                 t->fogtexture = NULL;
6970                 t->backgroundbasetexture = NULL;
6971                 t->backgroundnmaptexture = r_texture_blanknormalmap;
6972                 t->backgroundglosstexture = r_texture_black;
6973                 t->backgroundglowtexture = NULL;
6974                 t->specularscale = 0;
6975                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6976         }
6977
6978         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
6979         VectorClear(t->dlightcolor);
6980         t->currentnumlayers = 0;
6981         if (t->currentmaterialflags & MATERIALFLAG_WALL)
6982         {
6983                 int blendfunc1, blendfunc2;
6984                 qboolean depthmask;
6985                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6986                 {
6987                         blendfunc1 = GL_SRC_ALPHA;
6988                         blendfunc2 = GL_ONE;
6989                 }
6990                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6991                 {
6992                         blendfunc1 = GL_SRC_ALPHA;
6993                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6994                 }
6995                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6996                 {
6997                         blendfunc1 = t->customblendfunc[0];
6998                         blendfunc2 = t->customblendfunc[1];
6999                 }
7000                 else
7001                 {
7002                         blendfunc1 = GL_ONE;
7003                         blendfunc2 = GL_ZERO;
7004                 }
7005                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7006                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7007                 {
7008                         // fullbright is not affected by r_refdef.lightmapintensity
7009                         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]);
7010                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7011                                 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]);
7012                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7013                                 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]);
7014                 }
7015                 else
7016                 {
7017                         vec3_t ambientcolor;
7018                         float colorscale;
7019                         // set the color tint used for lights affecting this surface
7020                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7021                         colorscale = 2;
7022                         // q3bsp has no lightmap updates, so the lightstylevalue that
7023                         // would normally be baked into the lightmap must be
7024                         // applied to the color
7025                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7026                         if (model->type == mod_brushq3)
7027                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7028                         colorscale *= r_refdef.lightmapintensity;
7029                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7030                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7031                         // basic lit geometry
7032                         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]);
7033                         // add pants/shirt if needed
7034                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7035                                 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]);
7036                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7037                                 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]);
7038                         // now add ambient passes if needed
7039                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7040                         {
7041                                 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]);
7042                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7043                                         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]);
7044                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7045                                         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]);
7046                         }
7047                 }
7048                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7049                         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]);
7050                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7051                 {
7052                         // if this is opaque use alpha blend which will darken the earlier
7053                         // passes cheaply.
7054                         //
7055                         // if this is an alpha blended material, all the earlier passes
7056                         // were darkened by fog already, so we only need to add the fog
7057                         // color ontop through the fog mask texture
7058                         //
7059                         // if this is an additive blended material, all the earlier passes
7060                         // were darkened by fog already, and we should not add fog color
7061                         // (because the background was not darkened, there is no fog color
7062                         // that was lost behind it).
7063                         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]);
7064                 }
7065         }
7066
7067         return t->currentframe;
7068 }
7069
7070 rsurfacestate_t rsurface;
7071
7072 void R_Mesh_ResizeArrays(int newvertices)
7073 {
7074         float *base;
7075         if (rsurface.array_size >= newvertices)
7076                 return;
7077         if (rsurface.array_modelvertex3f)
7078                 Mem_Free(rsurface.array_modelvertex3f);
7079         rsurface.array_size = (newvertices + 1023) & ~1023;
7080         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
7081         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
7082         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
7083         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
7084         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
7085         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
7086         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
7087         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
7088         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
7089         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
7090         rsurface.array_color4f           = base + rsurface.array_size * 27;
7091         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
7092 }
7093
7094 void RSurf_ActiveWorldEntity(void)
7095 {
7096         dp_model_t *model = r_refdef.scene.worldmodel;
7097         //if (rsurface.entity == r_refdef.scene.worldentity)
7098         //      return;
7099         rsurface.entity = r_refdef.scene.worldentity;
7100         rsurface.skeleton = NULL;
7101         rsurface.ent_skinnum = 0;
7102         rsurface.ent_qwskin = -1;
7103         rsurface.ent_shadertime = 0;
7104         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7105         if (rsurface.array_size < model->surfmesh.num_vertices)
7106                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
7107         rsurface.matrix = identitymatrix;
7108         rsurface.inversematrix = identitymatrix;
7109         rsurface.matrixscale = 1;
7110         rsurface.inversematrixscale = 1;
7111         R_EntityMatrix(&identitymatrix);
7112         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7113         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7114         rsurface.fograngerecip = r_refdef.fograngerecip;
7115         rsurface.fogheightfade = r_refdef.fogheightfade;
7116         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7117         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7118         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7119         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7120         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7121         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7122         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7123         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7124         rsurface.colormod[3] = 1;
7125         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);
7126         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7127         rsurface.frameblend[0].lerp = 1;
7128         rsurface.ent_alttextures = false;
7129         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7130         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7131         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7132         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
7133         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7134         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7135         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
7136         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7137         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7138         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
7139         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7140         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7141         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
7142         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7143         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7144         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
7145         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7146         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7147         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
7148         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7149         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7150         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
7151         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7152         rsurface.modelelement3i = model->surfmesh.data_element3i;
7153         rsurface.modelelement3s = model->surfmesh.data_element3s;
7154         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
7155         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
7156         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7157         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
7158         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
7159         rsurface.modelsurfaces = model->data_surfaces;
7160         rsurface.generatedvertex = false;
7161         rsurface.vertex3f  = rsurface.modelvertex3f;
7162         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7163         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7164         rsurface.svector3f = rsurface.modelsvector3f;
7165         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7166         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7167         rsurface.tvector3f = rsurface.modeltvector3f;
7168         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7169         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7170         rsurface.normal3f  = rsurface.modelnormal3f;
7171         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7172         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7173         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7174 }
7175
7176 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7177 {
7178         dp_model_t *model = ent->model;
7179         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7180         //      return;
7181         rsurface.entity = (entity_render_t *)ent;
7182         rsurface.skeleton = ent->skeleton;
7183         rsurface.ent_skinnum = ent->skinnum;
7184         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;
7185         rsurface.ent_shadertime = ent->shadertime;
7186         rsurface.ent_flags = ent->flags;
7187         if (rsurface.array_size < model->surfmesh.num_vertices)
7188                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
7189         rsurface.matrix = ent->matrix;
7190         rsurface.inversematrix = ent->inversematrix;
7191         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7192         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7193         R_EntityMatrix(&rsurface.matrix);
7194         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7195         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7196         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7197         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7198         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7199         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7200         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7201         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7202         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7203         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7204         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7205         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7206         rsurface.colormod[3] = ent->alpha;
7207         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7208         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7209         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7210         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7211         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7212         if (ent->model->brush.submodel && !prepass)
7213         {
7214                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7215                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7216         }
7217         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7218         {
7219                 if (ent->animcache_vertex3f && !r_framedata_failed)
7220                 {
7221                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7222                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7223                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7224                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7225                 }
7226                 else if (wanttangents)
7227                 {
7228                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7229                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
7230                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
7231                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7232                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
7233                 }
7234                 else if (wantnormals)
7235                 {
7236                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7237                         rsurface.modelsvector3f = NULL;
7238                         rsurface.modeltvector3f = NULL;
7239                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7240                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
7241                 }
7242                 else
7243                 {
7244                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7245                         rsurface.modelsvector3f = NULL;
7246                         rsurface.modeltvector3f = NULL;
7247                         rsurface.modelnormal3f = NULL;
7248                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
7249                 }
7250                 rsurface.modelvertex3f_bufferobject = 0;
7251                 rsurface.modelvertex3f_bufferoffset = 0;
7252                 rsurface.modelsvector3f_bufferobject = 0;
7253                 rsurface.modelsvector3f_bufferoffset = 0;
7254                 rsurface.modeltvector3f_bufferobject = 0;
7255                 rsurface.modeltvector3f_bufferoffset = 0;
7256                 rsurface.modelnormal3f_bufferobject = 0;
7257                 rsurface.modelnormal3f_bufferoffset = 0;
7258                 rsurface.generatedvertex = true;
7259         }
7260         else
7261         {
7262                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7263                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
7264                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7265                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7266                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
7267                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7268                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7269                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
7270                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7271                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7272                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
7273                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7274                 rsurface.generatedvertex = false;
7275         }
7276         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7277         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
7278         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7279         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7280         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
7281         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7282         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7283         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
7284         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7285         rsurface.modelelement3i = model->surfmesh.data_element3i;
7286         rsurface.modelelement3s = model->surfmesh.data_element3s;
7287         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
7288         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
7289         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7290         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
7291         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
7292         rsurface.modelsurfaces = model->data_surfaces;
7293         rsurface.vertex3f  = rsurface.modelvertex3f;
7294         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7295         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7296         rsurface.svector3f = rsurface.modelsvector3f;
7297         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7298         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7299         rsurface.tvector3f = rsurface.modeltvector3f;
7300         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7301         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7302         rsurface.normal3f  = rsurface.modelnormal3f;
7303         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7304         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7305         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7306 }
7307
7308 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)
7309 {
7310         rsurface.entity = r_refdef.scene.worldentity;
7311         rsurface.skeleton = NULL;
7312         rsurface.ent_skinnum = 0;
7313         rsurface.ent_qwskin = -1;
7314         rsurface.ent_shadertime = shadertime;
7315         rsurface.ent_flags = entflags;
7316         rsurface.modelnum_vertices = numvertices;
7317         rsurface.modelnum_triangles = numtriangles;
7318         if (rsurface.array_size < rsurface.modelnum_vertices)
7319                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
7320         rsurface.matrix = *matrix;
7321         rsurface.inversematrix = *inversematrix;
7322         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7323         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7324         R_EntityMatrix(&rsurface.matrix);
7325         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7326         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7327         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7328         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7329         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7330         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7331         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7332         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7333         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7334         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7335         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7336         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7337         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);
7338         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7339         rsurface.frameblend[0].lerp = 1;
7340         rsurface.ent_alttextures = false;
7341         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7342         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7343         if (wanttangents)
7344         {
7345                 rsurface.modelvertex3f = vertex3f;
7346                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
7347                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
7348                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
7349         }
7350         else if (wantnormals)
7351         {
7352                 rsurface.modelvertex3f = vertex3f;
7353                 rsurface.modelsvector3f = NULL;
7354                 rsurface.modeltvector3f = NULL;
7355                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
7356         }
7357         else
7358         {
7359                 rsurface.modelvertex3f = vertex3f;
7360                 rsurface.modelsvector3f = NULL;
7361                 rsurface.modeltvector3f = NULL;
7362                 rsurface.modelnormal3f = NULL;
7363         }
7364         rsurface.modelvertex3f_bufferobject = 0;
7365         rsurface.modelvertex3f_bufferoffset = 0;
7366         rsurface.modelsvector3f_bufferobject = 0;
7367         rsurface.modelsvector3f_bufferoffset = 0;
7368         rsurface.modeltvector3f_bufferobject = 0;
7369         rsurface.modeltvector3f_bufferoffset = 0;
7370         rsurface.modelnormal3f_bufferobject = 0;
7371         rsurface.modelnormal3f_bufferoffset = 0;
7372         rsurface.generatedvertex = true;
7373         rsurface.modellightmapcolor4f  = color4f;
7374         rsurface.modellightmapcolor4f_bufferobject = 0;
7375         rsurface.modellightmapcolor4f_bufferoffset = 0;
7376         rsurface.modeltexcoordtexture2f  = texcoord2f;
7377         rsurface.modeltexcoordtexture2f_bufferobject = 0;
7378         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7379         rsurface.modeltexcoordlightmap2f  = NULL;
7380         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
7381         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7382         rsurface.modelelement3i = element3i;
7383         rsurface.modelelement3s = element3s;
7384         rsurface.modelelement3i_bufferobject = 0;
7385         rsurface.modelelement3s_bufferobject = 0;
7386         rsurface.modellightmapoffsets = NULL;
7387         rsurface.modelsurfaces = NULL;
7388         rsurface.vertex3f  = rsurface.modelvertex3f;
7389         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7390         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7391         rsurface.svector3f = rsurface.modelsvector3f;
7392         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7393         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7394         rsurface.tvector3f = rsurface.modeltvector3f;
7395         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7396         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7397         rsurface.normal3f  = rsurface.modelnormal3f;
7398         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7399         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7400         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7401
7402         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
7403         {
7404                 if ((wantnormals || wanttangents) && !normal3f)
7405                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7406                 if (wanttangents && !svector3f)
7407                         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);
7408         }
7409 }
7410
7411 float RSurf_FogPoint(const float *v)
7412 {
7413         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7414         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7415         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7416         float FogHeightFade = r_refdef.fogheightfade;
7417         float fogfrac;
7418         unsigned int fogmasktableindex;
7419         if (r_refdef.fogplaneviewabove)
7420                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7421         else
7422                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7423         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7424         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7425 }
7426
7427 float RSurf_FogVertex(const float *v)
7428 {
7429         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7430         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7431         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7432         float FogHeightFade = rsurface.fogheightfade;
7433         float fogfrac;
7434         unsigned int fogmasktableindex;
7435         if (r_refdef.fogplaneviewabove)
7436                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7437         else
7438                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7439         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7440         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7441 }
7442
7443 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
7444 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
7445 {
7446         int deformindex;
7447         int texturesurfaceindex;
7448         int i, j;
7449         float amplitude;
7450         float animpos;
7451         float scale;
7452         const float *v1, *in_tc;
7453         float *out_tc;
7454         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
7455         float waveparms[4];
7456         q3shaderinfo_deform_t *deform;
7457         // 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
7458         if (rsurface.generatedvertex)
7459         {
7460                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
7461                         generatenormals = true;
7462                 for (i = 0;i < Q3MAXDEFORMS;i++)
7463                 {
7464                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
7465                         {
7466                                 generatetangents = true;
7467                                 generatenormals = true;
7468                         }
7469                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
7470                                 generatenormals = true;
7471                 }
7472                 if (generatenormals && !rsurface.modelnormal3f)
7473                 {
7474                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7475                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
7476                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
7477                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7478                 }
7479                 if (generatetangents && !rsurface.modelsvector3f)
7480                 {
7481                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
7482                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
7483                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
7484                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
7485                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
7486                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
7487                         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);
7488                 }
7489         }
7490         rsurface.vertex3f  = rsurface.modelvertex3f;
7491         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7492         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7493         rsurface.svector3f = rsurface.modelsvector3f;
7494         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7495         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7496         rsurface.tvector3f = rsurface.modeltvector3f;
7497         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7498         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7499         rsurface.normal3f  = rsurface.modelnormal3f;
7500         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7501         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7502         // if vertices are deformed (sprite flares and things in maps, possibly
7503         // water waves, bulges and other deformations), generate them into
7504         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
7505         // (may be static model data or generated data for an animated model, or
7506         //  the previous deform pass)
7507         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
7508         {
7509                 switch (deform->deform)
7510                 {
7511                 default:
7512                 case Q3DEFORM_PROJECTIONSHADOW:
7513                 case Q3DEFORM_TEXT0:
7514                 case Q3DEFORM_TEXT1:
7515                 case Q3DEFORM_TEXT2:
7516                 case Q3DEFORM_TEXT3:
7517                 case Q3DEFORM_TEXT4:
7518                 case Q3DEFORM_TEXT5:
7519                 case Q3DEFORM_TEXT6:
7520                 case Q3DEFORM_TEXT7:
7521                 case Q3DEFORM_NONE:
7522                         break;
7523                 case Q3DEFORM_AUTOSPRITE:
7524                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
7525                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
7526                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
7527                         VectorNormalize(newforward);
7528                         VectorNormalize(newright);
7529                         VectorNormalize(newup);
7530                         // make deformed versions of only the model vertices used by the specified surfaces
7531                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7532                         {
7533                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7534                                 // a single autosprite surface can contain multiple sprites...
7535                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
7536                                 {
7537                                         VectorClear(center);
7538                                         for (i = 0;i < 4;i++)
7539                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
7540                                         VectorScale(center, 0.25f, center);
7541                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
7542                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
7543                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
7544                                         for (i = 0;i < 4;i++)
7545                                         {
7546                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
7547                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
7548                                         }
7549                                 }
7550                                 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);
7551                                 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);
7552                         }
7553                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7554                         rsurface.vertex3f_bufferobject = 0;
7555                         rsurface.vertex3f_bufferoffset = 0;
7556                         rsurface.svector3f = rsurface.array_deformedsvector3f;
7557                         rsurface.svector3f_bufferobject = 0;
7558                         rsurface.svector3f_bufferoffset = 0;
7559                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
7560                         rsurface.tvector3f_bufferobject = 0;
7561                         rsurface.tvector3f_bufferoffset = 0;
7562                         rsurface.normal3f = rsurface.array_deformednormal3f;
7563                         rsurface.normal3f_bufferobject = 0;
7564                         rsurface.normal3f_bufferoffset = 0;
7565                         break;
7566                 case Q3DEFORM_AUTOSPRITE2:
7567                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
7568                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
7569                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
7570                         VectorNormalize(newforward);
7571                         VectorNormalize(newright);
7572                         VectorNormalize(newup);
7573                         // make deformed versions of only the model vertices used by the specified surfaces
7574                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7575                         {
7576                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7577                                 const float *v1, *v2;
7578                                 vec3_t start, end;
7579                                 float f, l;
7580                                 struct
7581                                 {
7582                                         float length2;
7583                                         const float *v1;
7584                                         const float *v2;
7585                                 }
7586                                 shortest[2];
7587                                 memset(shortest, 0, sizeof(shortest));
7588                                 // a single autosprite surface can contain multiple sprites...
7589                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
7590                                 {
7591                                         VectorClear(center);
7592                                         for (i = 0;i < 4;i++)
7593                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
7594                                         VectorScale(center, 0.25f, center);
7595                                         // find the two shortest edges, then use them to define the
7596                                         // axis vectors for rotating around the central axis
7597                                         for (i = 0;i < 6;i++)
7598                                         {
7599                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
7600                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
7601 #if 0
7602                                                 Debug_PolygonBegin(NULL, 0);
7603                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
7604                                                 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);
7605                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
7606                                                 Debug_PolygonEnd();
7607 #endif
7608                                                 l = VectorDistance2(v1, v2);
7609                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
7610                                                 if (v1[2] != v2[2])
7611                                                         l += (1.0f / 1024.0f);
7612                                                 if (shortest[0].length2 > l || i == 0)
7613                                                 {
7614                                                         shortest[1] = shortest[0];
7615                                                         shortest[0].length2 = l;
7616                                                         shortest[0].v1 = v1;
7617                                                         shortest[0].v2 = v2;
7618                                                 }
7619                                                 else if (shortest[1].length2 > l || i == 1)
7620                                                 {
7621                                                         shortest[1].length2 = l;
7622                                                         shortest[1].v1 = v1;
7623                                                         shortest[1].v2 = v2;
7624                                                 }
7625                                         }
7626                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
7627                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
7628 #if 0
7629                                         Debug_PolygonBegin(NULL, 0);
7630                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
7631                                         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);
7632                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
7633                                         Debug_PolygonEnd();
7634 #endif
7635                                         // this calculates the right vector from the shortest edge
7636                                         // and the up vector from the edge midpoints
7637                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
7638                                         VectorNormalize(right);
7639                                         VectorSubtract(end, start, up);
7640                                         VectorNormalize(up);
7641                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
7642                                         VectorSubtract(rsurface.localvieworigin, center, forward);
7643                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
7644                                         VectorNegate(forward, forward);
7645                                         VectorReflect(forward, 0, up, forward);
7646                                         VectorNormalize(forward);
7647                                         CrossProduct(up, forward, newright);
7648                                         VectorNormalize(newright);
7649 #if 0
7650                                         Debug_PolygonBegin(NULL, 0);
7651                                         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);
7652                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
7653                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
7654                                         Debug_PolygonEnd();
7655 #endif
7656 #if 0
7657                                         Debug_PolygonBegin(NULL, 0);
7658                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
7659                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
7660                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
7661                                         Debug_PolygonEnd();
7662 #endif
7663                                         // rotate the quad around the up axis vector, this is made
7664                                         // especially easy by the fact we know the quad is flat,
7665                                         // so we only have to subtract the center position and
7666                                         // measure distance along the right vector, and then
7667                                         // multiply that by the newright vector and add back the
7668                                         // center position
7669                                         // we also need to subtract the old position to undo the
7670                                         // displacement from the center, which we do with a
7671                                         // DotProduct, the subtraction/addition of center is also
7672                                         // optimized into DotProducts here
7673                                         l = DotProduct(right, center);
7674                                         for (i = 0;i < 4;i++)
7675                                         {
7676                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
7677                                                 f = DotProduct(right, v1) - l;
7678                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
7679                                         }
7680                                 }
7681                                 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);
7682                                 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);
7683                         }
7684                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7685                         rsurface.vertex3f_bufferobject = 0;
7686                         rsurface.vertex3f_bufferoffset = 0;
7687                         rsurface.svector3f = rsurface.array_deformedsvector3f;
7688                         rsurface.svector3f_bufferobject = 0;
7689                         rsurface.svector3f_bufferoffset = 0;
7690                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
7691                         rsurface.tvector3f_bufferobject = 0;
7692                         rsurface.tvector3f_bufferoffset = 0;
7693                         rsurface.normal3f = rsurface.array_deformednormal3f;
7694                         rsurface.normal3f_bufferobject = 0;
7695                         rsurface.normal3f_bufferoffset = 0;
7696                         break;
7697                 case Q3DEFORM_NORMAL:
7698                         // deform the normals to make reflections wavey
7699                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7700                         {
7701                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7702                                 for (j = 0;j < surface->num_vertices;j++)
7703                                 {
7704                                         float vertex[3];
7705                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
7706                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
7707                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
7708                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7709                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7710                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7711                                         VectorNormalize(normal);
7712                                 }
7713                                 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);
7714                         }
7715                         rsurface.svector3f = rsurface.array_deformedsvector3f;
7716                         rsurface.svector3f_bufferobject = 0;
7717                         rsurface.svector3f_bufferoffset = 0;
7718                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
7719                         rsurface.tvector3f_bufferobject = 0;
7720                         rsurface.tvector3f_bufferoffset = 0;
7721                         rsurface.normal3f = rsurface.array_deformednormal3f;
7722                         rsurface.normal3f_bufferobject = 0;
7723                         rsurface.normal3f_bufferoffset = 0;
7724                         break;
7725                 case Q3DEFORM_WAVE:
7726                         // deform vertex array to make wavey water and flags and such
7727                         waveparms[0] = deform->waveparms[0];
7728                         waveparms[1] = deform->waveparms[1];
7729                         waveparms[2] = deform->waveparms[2];
7730                         waveparms[3] = deform->waveparms[3];
7731                         // this is how a divisor of vertex influence on deformation
7732                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
7733                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
7734                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7735                         {
7736                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7737                                 for (j = 0;j < surface->num_vertices;j++)
7738                                 {
7739                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
7740                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
7741                                         // if the wavefunc depends on time, evaluate it per-vertex
7742                                         if (waveparms[3])
7743                                         {
7744                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
7745                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
7746                                         }
7747                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
7748                                 }
7749                         }
7750                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7751                         rsurface.vertex3f_bufferobject = 0;
7752                         rsurface.vertex3f_bufferoffset = 0;
7753                         break;
7754                 case Q3DEFORM_BULGE:
7755                         // deform vertex array to make the surface have moving bulges
7756                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7757                         {
7758                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7759                                 for (j = 0;j < surface->num_vertices;j++)
7760                                 {
7761                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
7762                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
7763                                 }
7764                         }
7765                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7766                         rsurface.vertex3f_bufferobject = 0;
7767                         rsurface.vertex3f_bufferoffset = 0;
7768                         break;
7769                 case Q3DEFORM_MOVE:
7770                         // deform vertex array
7771                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
7772                         VectorScale(deform->parms, scale, waveparms);
7773                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7774                         {
7775                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7776                                 for (j = 0;j < surface->num_vertices;j++)
7777                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
7778                         }
7779                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7780                         rsurface.vertex3f_bufferobject = 0;
7781                         rsurface.vertex3f_bufferoffset = 0;
7782                         break;
7783                 }
7784         }
7785         // generate texcoords based on the chosen texcoord source
7786         switch(rsurface.texture->tcgen.tcgen)
7787         {
7788         default:
7789         case Q3TCGEN_TEXTURE:
7790                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
7791                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
7792                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
7793                 break;
7794         case Q3TCGEN_LIGHTMAP:
7795                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
7796                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
7797                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
7798                 break;
7799         case Q3TCGEN_VECTOR:
7800                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7801                 {
7802                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7803                         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)
7804                         {
7805                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
7806                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
7807                         }
7808                 }
7809                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7810                 rsurface.texcoordtexture2f_bufferobject  = 0;
7811                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7812                 break;
7813         case Q3TCGEN_ENVIRONMENT:
7814                 // make environment reflections using a spheremap
7815                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7816                 {
7817                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7818                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
7819                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
7820                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
7821                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
7822                         {
7823                                 // identical to Q3A's method, but executed in worldspace so
7824                                 // carried models can be shiny too
7825
7826                                 float viewer[3], d, reflected[3], worldreflected[3];
7827
7828                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
7829                                 // VectorNormalize(viewer);
7830
7831                                 d = DotProduct(normal, viewer);
7832
7833                                 reflected[0] = normal[0]*2*d - viewer[0];
7834                                 reflected[1] = normal[1]*2*d - viewer[1];
7835                                 reflected[2] = normal[2]*2*d - viewer[2];
7836                                 // note: this is proportinal to viewer, so we can normalize later
7837
7838                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7839                                 VectorNormalize(worldreflected);
7840
7841                                 // note: this sphere map only uses world x and z!
7842                                 // so positive and negative y will LOOK THE SAME.
7843                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7844                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7845                         }
7846                 }
7847                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7848                 rsurface.texcoordtexture2f_bufferobject  = 0;
7849                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7850                 break;
7851         }
7852         // the only tcmod that needs software vertex processing is turbulent, so
7853         // check for it here and apply the changes if needed
7854         // and we only support that as the first one
7855         // (handling a mixture of turbulent and other tcmods would be problematic
7856         //  without punting it entirely to a software path)
7857         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7858         {
7859                 amplitude = rsurface.texture->tcmods[0].parms[1];
7860                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7861                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7862                 {
7863                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7864                         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)
7865                         {
7866                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7867                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7868                         }
7869                 }
7870                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7871                 rsurface.texcoordtexture2f_bufferobject  = 0;
7872                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7873         }
7874         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
7875         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7876         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7877         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7878 }
7879
7880 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7881 {
7882         int i, j;
7883         const msurface_t *surface = texturesurfacelist[0];
7884         const msurface_t *surface2;
7885         int firstvertex;
7886         int endvertex;
7887         int numvertices;
7888         int numtriangles;
7889         // TODO: lock all array ranges before render, rather than on each surface
7890         if (texturenumsurfaces == 1)
7891         {
7892                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7893                 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);
7894         }
7895         else if (r_batchmode.integer == 2)
7896         {
7897                 #define MAXBATCHTRIANGLES 4096
7898                 int batchtriangles = 0;
7899                 static int batchelements[MAXBATCHTRIANGLES*3];
7900                 for (i = 0;i < texturenumsurfaces;i = j)
7901                 {
7902                         surface = texturesurfacelist[i];
7903                         j = i + 1;
7904                         if (surface->num_triangles > MAXBATCHTRIANGLES)
7905                         {
7906                                 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);
7907                                 continue;
7908                         }
7909                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7910                         batchtriangles = surface->num_triangles;
7911                         firstvertex = surface->num_firstvertex;
7912                         endvertex = surface->num_firstvertex + surface->num_vertices;
7913                         for (;j < texturenumsurfaces;j++)
7914                         {
7915                                 surface2 = texturesurfacelist[j];
7916                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7917                                         break;
7918                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7919                                 batchtriangles += surface2->num_triangles;
7920                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
7921                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7922                         }
7923                         surface2 = texturesurfacelist[j-1];
7924                         numvertices = endvertex - firstvertex;
7925                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7926                 }
7927         }
7928         else if (r_batchmode.integer == 1)
7929         {
7930                 for (i = 0;i < texturenumsurfaces;i = j)
7931                 {
7932                         surface = texturesurfacelist[i];
7933                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7934                                 if (texturesurfacelist[j] != surface2)
7935                                         break;
7936                         surface2 = texturesurfacelist[j-1];
7937                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7938                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7939                         GL_LockArrays(surface->num_firstvertex, numvertices);
7940                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7941                 }
7942         }
7943         else
7944         {
7945                 for (i = 0;i < texturenumsurfaces;i++)
7946                 {
7947                         surface = texturesurfacelist[i];
7948                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7949                         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);
7950                 }
7951         }
7952 }
7953
7954 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
7955 {
7956         switch(vid.renderpath)
7957         {
7958         case RENDERPATH_CGGL:
7959 #ifdef SUPPORTCG
7960                 if (r_cg_permutation->fp_Texture_Lightmap ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Lightmap , R_GetTexture(surface->lightmaptexture ));
7961                 if (r_cg_permutation->fp_Texture_Deluxemap) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Deluxemap, R_GetTexture(surface->deluxemaptexture));
7962 #endif
7963                 break;
7964         case RENDERPATH_GL20:
7965                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(surface->lightmaptexture ));
7966                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, R_GetTexture(surface->deluxemaptexture));
7967                 break;
7968         case RENDERPATH_GL13:
7969         case RENDERPATH_GL11:
7970                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
7971                 break;
7972         }
7973 }
7974
7975 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
7976 {
7977         // pick the closest matching water plane and bind textures
7978         int planeindex, vertexindex;
7979         float d, bestd;
7980         vec3_t vert;
7981         const float *v;
7982         r_waterstate_waterplane_t *p, *bestp;
7983         bestd = 0;
7984         bestp = NULL;
7985         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7986         {
7987                 d = 0;
7988                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7989                 {
7990                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
7991                         d += fabs(PlaneDiff(vert, &p->plane));
7992                 }
7993                 if (bestd > d || !bestp)
7994                 {
7995                         bestd = d;
7996                         bestp = p;
7997                 }
7998         }
7999         switch(vid.renderpath)
8000         {
8001         case RENDERPATH_CGGL:
8002 #ifdef SUPPORTCG
8003                 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));
8004                 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));
8005 #endif
8006                 break;
8007         case RENDERPATH_GL20:
8008                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));
8009                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));
8010                 break;
8011         case RENDERPATH_GL13:
8012         case RENDERPATH_GL11:
8013                 break;
8014         }
8015 }
8016
8017 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8018 {
8019         int i;
8020         const msurface_t *surface;
8021         if (r_waterstate.renderingscene)
8022                 return;
8023         for (i = 0;i < texturenumsurfaces;i++)
8024         {
8025                 surface = texturesurfacelist[i];
8026                 RSurf_BindLightmapForSurface(surface);
8027                 RSurf_BindReflectionForSurface(surface);
8028                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8029                 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);
8030         }
8031 }
8032
8033 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8034 {
8035         int i;
8036         int j;
8037         const msurface_t *surface = texturesurfacelist[0];
8038         const msurface_t *surface2;
8039         int firstvertex;
8040         int endvertex;
8041         int numvertices;
8042         int numtriangles;
8043         if (texturenumsurfaces == 1)
8044         {
8045                 RSurf_BindLightmapForSurface(surface);
8046                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8047                 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);
8048         }
8049         else if (r_batchmode.integer == 2)
8050         {
8051 #define MAXBATCHTRIANGLES 4096
8052                 int batchtriangles = 0;
8053                 static int batchelements[MAXBATCHTRIANGLES*3];
8054                 for (i = 0;i < texturenumsurfaces;i = j)
8055                 {
8056                         surface = texturesurfacelist[i];
8057                         RSurf_BindLightmapForSurface(surface);
8058                         j = i + 1;
8059                         if (surface->num_triangles > MAXBATCHTRIANGLES)
8060                         {
8061                                 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);
8062                                 continue;
8063                         }
8064                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
8065                         batchtriangles = surface->num_triangles;
8066                         firstvertex = surface->num_firstvertex;
8067                         endvertex = surface->num_firstvertex + surface->num_vertices;
8068                         for (;j < texturenumsurfaces;j++)
8069                         {
8070                                 surface2 = texturesurfacelist[j];
8071                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
8072                                         break;
8073                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
8074                                 batchtriangles += surface2->num_triangles;
8075                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
8076                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
8077                         }
8078                         surface2 = texturesurfacelist[j-1];
8079                         numvertices = endvertex - firstvertex;
8080                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
8081                 }
8082         }
8083         else if (r_batchmode.integer == 1)
8084         {
8085 #if 0
8086                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
8087                 for (i = 0;i < texturenumsurfaces;i = j)
8088                 {
8089                         surface = texturesurfacelist[i];
8090                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
8091                                 if (texturesurfacelist[j] != surface2)
8092                                         break;
8093                         Con_Printf(" %i", j - i);
8094                 }
8095                 Con_Printf("\n");
8096                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
8097 #endif
8098                 for (i = 0;i < texturenumsurfaces;i = j)
8099                 {
8100                         surface = texturesurfacelist[i];
8101                         RSurf_BindLightmapForSurface(surface);
8102                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
8103                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
8104                                         break;
8105 #if 0
8106                         Con_Printf(" %i", j - i);
8107 #endif
8108                         surface2 = texturesurfacelist[j-1];
8109                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
8110                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
8111                         GL_LockArrays(surface->num_firstvertex, numvertices);
8112                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
8113                 }
8114 #if 0
8115                 Con_Printf("\n");
8116 #endif
8117         }
8118         else
8119         {
8120                 for (i = 0;i < texturenumsurfaces;i++)
8121                 {
8122                         surface = texturesurfacelist[i];
8123                         RSurf_BindLightmapForSurface(surface);
8124                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8125                         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);
8126                 }
8127         }
8128 }
8129
8130 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8131 {
8132         int j;
8133         int texturesurfaceindex;
8134         if (r_showsurfaces.integer == 2)
8135         {
8136                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8137                 {
8138                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8139                         for (j = 0;j < surface->num_triangles;j++)
8140                         {
8141                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
8142                                 GL_Color(f, f, f, 1);
8143                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
8144                         }
8145                 }
8146         }
8147         else
8148         {
8149                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8150                 {
8151                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8152                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
8153                         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);
8154                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8155                         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);
8156                 }
8157         }
8158 }
8159
8160 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8161 {
8162         int texturesurfaceindex;
8163         int i;
8164         const float *v;
8165         float *c2;
8166         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8167         {
8168                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8169                 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)
8170                 {
8171                         c2[0] = 0.5;
8172                         c2[1] = 0.5;
8173                         c2[2] = 0.5;
8174                         c2[3] = 1;
8175                 }
8176         }
8177         rsurface.lightmapcolor4f = rsurface.array_color4f;
8178         rsurface.lightmapcolor4f_bufferobject = 0;
8179         rsurface.lightmapcolor4f_bufferoffset = 0;
8180 }
8181
8182 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8183 {
8184         int texturesurfaceindex;
8185         int i;
8186         float f;
8187         const float *v;
8188         const float *c;
8189         float *c2;
8190         if (rsurface.lightmapcolor4f)
8191         {
8192                 // generate color arrays for the surfaces in this list
8193                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8194                 {
8195                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8196                         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)
8197                         {
8198                                 f = RSurf_FogVertex(v);
8199                                 c2[0] = c[0] * f;
8200                                 c2[1] = c[1] * f;
8201                                 c2[2] = c[2] * f;
8202                                 c2[3] = c[3];
8203                         }
8204                 }
8205         }
8206         else
8207         {
8208                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8209                 {
8210                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8211                         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)
8212                         {
8213                                 f = RSurf_FogVertex(v);
8214                                 c2[0] = f;
8215                                 c2[1] = f;
8216                                 c2[2] = f;
8217                                 c2[3] = 1;
8218                         }
8219                 }
8220         }
8221         rsurface.lightmapcolor4f = rsurface.array_color4f;
8222         rsurface.lightmapcolor4f_bufferobject = 0;
8223         rsurface.lightmapcolor4f_bufferoffset = 0;
8224 }
8225
8226 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8227 {
8228         int texturesurfaceindex;
8229         int i;
8230         float f;
8231         const float *v;
8232         const float *c;
8233         float *c2;
8234         if (!rsurface.lightmapcolor4f)
8235                 return;
8236         // generate color arrays for the surfaces in this list
8237         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8238         {
8239                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8240                 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)
8241                 {
8242                         f = RSurf_FogVertex(v);
8243                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8244                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8245                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8246                         c2[3] = c[3];
8247                 }
8248         }
8249         rsurface.lightmapcolor4f = rsurface.array_color4f;
8250         rsurface.lightmapcolor4f_bufferobject = 0;
8251         rsurface.lightmapcolor4f_bufferoffset = 0;
8252 }
8253
8254 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
8255 {
8256         int texturesurfaceindex;
8257         int i;
8258         const float *c;
8259         float *c2;
8260         if (!rsurface.lightmapcolor4f)
8261                 return;
8262         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8263         {
8264                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8265                 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)
8266                 {
8267                         c2[0] = c[0] * r;
8268                         c2[1] = c[1] * g;
8269                         c2[2] = c[2] * b;
8270                         c2[3] = c[3] * a;
8271                 }
8272         }
8273         rsurface.lightmapcolor4f = rsurface.array_color4f;
8274         rsurface.lightmapcolor4f_bufferobject = 0;
8275         rsurface.lightmapcolor4f_bufferoffset = 0;
8276 }
8277
8278 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8279 {
8280         int texturesurfaceindex;
8281         int i;
8282         const float *c;
8283         float *c2;
8284         if (!rsurface.lightmapcolor4f)
8285                 return;
8286         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8287         {
8288                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8289                 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)
8290                 {
8291                         c2[0] = c[0] + r_refdef.scene.ambient;
8292                         c2[1] = c[1] + r_refdef.scene.ambient;
8293                         c2[2] = c[2] + r_refdef.scene.ambient;
8294                         c2[3] = c[3];
8295                 }
8296         }
8297         rsurface.lightmapcolor4f = rsurface.array_color4f;
8298         rsurface.lightmapcolor4f_bufferobject = 0;
8299         rsurface.lightmapcolor4f_bufferoffset = 0;
8300 }
8301
8302 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8303 {
8304         // TODO: optimize
8305         rsurface.lightmapcolor4f = NULL;
8306         rsurface.lightmapcolor4f_bufferobject = 0;
8307         rsurface.lightmapcolor4f_bufferoffset = 0;
8308         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8309         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8310         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8311         GL_Color(r, g, b, a);
8312         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
8313 }
8314
8315 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8316 {
8317         // TODO: optimize applyfog && applycolor case
8318         // just apply fog if necessary, and tint the fog color array if necessary
8319         rsurface.lightmapcolor4f = NULL;
8320         rsurface.lightmapcolor4f_bufferobject = 0;
8321         rsurface.lightmapcolor4f_bufferoffset = 0;
8322         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8323         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8324         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8325         GL_Color(r, g, b, a);
8326         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8327 }
8328
8329 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8330 {
8331         int texturesurfaceindex;
8332         int i;
8333         float *c;
8334         // TODO: optimize
8335         if (texturesurfacelist[0]->lightmapinfo)
8336         {
8337                 // generate color arrays for the surfaces in this list
8338                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8339                 {
8340                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8341                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
8342                         {
8343                                 if (surface->lightmapinfo->samples)
8344                                 {
8345                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
8346                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
8347                                         VectorScale(lm, scale, c);
8348                                         if (surface->lightmapinfo->styles[1] != 255)
8349                                         {
8350                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8351                                                 lm += size3;
8352                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
8353                                                 VectorMA(c, scale, lm, c);
8354                                                 if (surface->lightmapinfo->styles[2] != 255)
8355                                                 {
8356                                                         lm += size3;
8357                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
8358                                                         VectorMA(c, scale, lm, c);
8359                                                         if (surface->lightmapinfo->styles[3] != 255)
8360                                                         {
8361                                                                 lm += size3;
8362                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
8363                                                                 VectorMA(c, scale, lm, c);
8364                                                         }
8365                                                 }
8366                                         }
8367                                 }
8368                                 else
8369                                         VectorClear(c);
8370                                 c[3] = 1;
8371                         }
8372                 }
8373                 rsurface.lightmapcolor4f = rsurface.array_color4f;
8374                 rsurface.lightmapcolor4f_bufferobject = 0;
8375                 rsurface.lightmapcolor4f_bufferoffset = 0;
8376         }
8377         else
8378         {
8379                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8380                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8381                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8382         }
8383         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8384         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8385         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8386         GL_Color(r, g, b, a);
8387         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8388 }
8389
8390 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
8391 {
8392         int texturesurfaceindex;
8393         int i;
8394         float f;
8395         float alpha;
8396         const float *v;
8397         const float *n;
8398         float *c;
8399         vec3_t ambientcolor;
8400         vec3_t diffusecolor;
8401         vec3_t lightdir;
8402         // TODO: optimize
8403         // model lighting
8404         VectorCopy(rsurface.modellight_lightdir, lightdir);
8405         f = 0.5f * r_refdef.lightmapintensity;
8406         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
8407         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
8408         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
8409         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
8410         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
8411         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
8412         alpha = *a;
8413         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
8414         {
8415                 // generate color arrays for the surfaces in this list
8416                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8417                 {
8418                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8419                         int numverts = surface->num_vertices;
8420                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
8421                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
8422                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
8423                         // q3-style directional shading
8424                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
8425                         {
8426                                 if ((f = DotProduct(n, lightdir)) > 0)
8427                                         VectorMA(ambientcolor, f, diffusecolor, c);
8428                                 else
8429                                         VectorCopy(ambientcolor, c);
8430                                 c[3] = alpha;
8431                         }
8432                 }
8433                 *r = 1;
8434                 *g = 1;
8435                 *b = 1;
8436                 *a = 1;
8437                 rsurface.lightmapcolor4f = rsurface.array_color4f;
8438                 rsurface.lightmapcolor4f_bufferobject = 0;
8439                 rsurface.lightmapcolor4f_bufferoffset = 0;
8440                 *applycolor = false;
8441         }
8442         else
8443         {
8444                 *r = ambientcolor[0];
8445                 *g = ambientcolor[1];
8446                 *b = ambientcolor[2];
8447                 rsurface.lightmapcolor4f = NULL;
8448                 rsurface.lightmapcolor4f_bufferobject = 0;
8449                 rsurface.lightmapcolor4f_bufferoffset = 0;
8450         }
8451 }
8452
8453 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8454 {
8455         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
8456         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8457         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8458         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8459         GL_Color(r, g, b, a);
8460         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8461 }
8462
8463 void RSurf_SetupDepthAndCulling(void)
8464 {
8465         // submodels are biased to avoid z-fighting with world surfaces that they
8466         // may be exactly overlapping (avoids z-fighting artifacts on certain
8467         // doors and things in Quake maps)
8468         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
8469         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
8470         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
8471         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
8472 }
8473
8474 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8475 {
8476         // transparent sky would be ridiculous
8477         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8478                 return;
8479         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8480         skyrenderlater = true;
8481         RSurf_SetupDepthAndCulling();
8482         GL_DepthMask(true);
8483         // LordHavoc: HalfLife maps have freaky skypolys so don't use
8484         // skymasking on them, and Quake3 never did sky masking (unlike
8485         // software Quake and software Quake2), so disable the sky masking
8486         // in Quake3 maps as it causes problems with q3map2 sky tricks,
8487         // and skymasking also looks very bad when noclipping outside the
8488         // level, so don't use it then either.
8489         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
8490         {
8491                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
8492                 R_Mesh_ColorPointer(NULL, 0, 0);
8493                 R_Mesh_ResetTextureState();
8494                 if (skyrendermasked)
8495                 {
8496                         R_SetupShader_DepthOrShadow();
8497                         // depth-only (masking)
8498                         GL_ColorMask(0,0,0,0);
8499                         // just to make sure that braindead drivers don't draw
8500                         // anything despite that colormask...
8501                         GL_BlendFunc(GL_ZERO, GL_ONE);
8502                 }
8503                 else
8504                 {
8505                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8506                         // fog sky
8507                         GL_BlendFunc(GL_ONE, GL_ZERO);
8508                 }
8509                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8510                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8511                 if (skyrendermasked)
8512                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8513         }
8514         R_Mesh_ResetTextureState();
8515         GL_Color(1, 1, 1, 1);
8516 }
8517
8518 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
8519 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
8520 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8521 {
8522         qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
8523         qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
8524
8525         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
8526                 return;
8527
8528         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
8529                 R_Mesh_ColorPointer(NULL, 0, 0);
8530         else
8531                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
8532
8533         if (refract)
8534         {
8535                 // render background
8536                 GL_BlendFunc(GL_ONE, GL_ZERO);
8537                 GL_DepthMask(true);
8538                 GL_AlphaTest(false);
8539
8540                 GL_Color(1, 1, 1, 1);
8541                 R_Mesh_ColorPointer(NULL, 0, 0);
8542
8543                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
8544                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
8545                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8546                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
8547                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
8548                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
8549                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8550                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8551                 GL_LockArrays(0, 0);
8552
8553                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
8554                 GL_DepthMask(false);
8555                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
8556                         R_Mesh_ColorPointer(NULL, 0, 0);
8557                 else
8558                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
8559         }
8560
8561         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
8562
8563         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
8564         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8565         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
8566         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
8567         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
8568         if (!prepass)
8569                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8570
8571         if (refract)
8572         {
8573                 GL_BlendFunc(GL_ONE, GL_ZERO);
8574                 GL_DepthMask(true);
8575                 GL_AlphaTest(false);
8576         }
8577         else
8578         {
8579                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
8580                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8581                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
8582         }
8583
8584         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8585         {
8586                 if (refract || reflect)
8587                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8588                 else
8589                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
8590         }
8591         else
8592         {
8593                 if (refract || reflect)
8594                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8595                 else
8596                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8597         }
8598         GL_LockArrays(0, 0);
8599 }
8600
8601 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8602 {
8603         // OpenGL 1.3 path - anything not completely ancient
8604         int texturesurfaceindex;
8605         qboolean applycolor;
8606         qboolean applyfog;
8607         int layerindex;
8608         const texturelayer_t *layer;
8609         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8610
8611         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
8612         {
8613                 vec4_t layercolor;
8614                 int layertexrgbscale;
8615                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8616                 {
8617                         if (layerindex == 0)
8618                                 GL_AlphaTest(true);
8619                         else
8620                         {
8621                                 GL_AlphaTest(false);
8622                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
8623                         }
8624                 }
8625                 GL_DepthMask(layer->depthmask && writedepth);
8626                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
8627                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
8628                 {
8629                         layertexrgbscale = 4;
8630                         VectorScale(layer->color, 0.25f, layercolor);
8631                 }
8632                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
8633                 {
8634                         layertexrgbscale = 2;
8635                         VectorScale(layer->color, 0.5f, layercolor);
8636                 }
8637                 else
8638                 {
8639                         layertexrgbscale = 1;
8640                         VectorScale(layer->color, 1.0f, layercolor);
8641                 }
8642                 layercolor[3] = layer->color[3];
8643                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
8644                 R_Mesh_ColorPointer(NULL, 0, 0);
8645                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
8646                 switch (layer->type)
8647                 {
8648                 case TEXTURELAYERTYPE_LITTEXTURE:
8649                         // single-pass lightmapped texture with 2x rgbscale
8650                         //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8651                         R_Mesh_TexMatrix(0, NULL);
8652                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8653                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8654                         R_Mesh_TexBind(1, R_GetTexture(layer->texture));
8655                         R_Mesh_TexMatrix(1, &layer->texmatrix);
8656                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8657                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8658                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8659                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8660                         else if (rsurface.uselightmaptexture)
8661                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8662                         else
8663                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8664                         break;
8665                 case TEXTURELAYERTYPE_TEXTURE:
8666                         // singletexture unlit texture with transparency support
8667                         R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8668                         R_Mesh_TexMatrix(0, &layer->texmatrix);
8669                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8670                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8671                         R_Mesh_TexBind(1, 0);
8672                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
8673                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8674                         break;
8675                 case TEXTURELAYERTYPE_FOG:
8676                         // singletexture fogging
8677                         if (layer->texture)
8678                         {
8679                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8680                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8681                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8682                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8683                         }
8684                         else
8685                         {
8686                                 R_Mesh_TexBind(0, 0);
8687                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8688                         }
8689                         R_Mesh_TexBind(1, 0);
8690                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
8691                         // generate a color array for the fog pass
8692                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8693                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8694                         {
8695                                 int i;
8696                                 float f;
8697                                 const float *v;
8698                                 float *c;
8699                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8700                                 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)
8701                                 {
8702                                         f = 1 - RSurf_FogVertex(v);
8703                                         c[0] = layercolor[0];
8704                                         c[1] = layercolor[1];
8705                                         c[2] = layercolor[2];
8706                                         c[3] = f * layercolor[3];
8707                                 }
8708                         }
8709                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8710                         break;
8711                 default:
8712                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8713                 }
8714                 GL_LockArrays(0, 0);
8715         }
8716         CHECKGLERROR
8717         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8718         {
8719                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8720                 GL_AlphaTest(false);
8721         }
8722 }
8723
8724 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8725 {
8726         // OpenGL 1.1 - crusty old voodoo path
8727         int texturesurfaceindex;
8728         qboolean applyfog;
8729         int layerindex;
8730         const texturelayer_t *layer;
8731         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8732
8733         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
8734         {
8735                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8736                 {
8737                         if (layerindex == 0)
8738                                 GL_AlphaTest(true);
8739                         else
8740                         {
8741                                 GL_AlphaTest(false);
8742                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
8743                         }
8744                 }
8745                 GL_DepthMask(layer->depthmask && writedepth);
8746                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
8747                 R_Mesh_ColorPointer(NULL, 0, 0);
8748                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
8749                 switch (layer->type)
8750                 {
8751                 case TEXTURELAYERTYPE_LITTEXTURE:
8752                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
8753                         {
8754                                 // two-pass lit texture with 2x rgbscale
8755                                 // first the lightmap pass
8756                                 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8757                                 R_Mesh_TexMatrix(0, NULL);
8758                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8759                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8760                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8761                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8762                                 else if (rsurface.uselightmaptexture)
8763                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8764                                 else
8765                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8766                                 GL_LockArrays(0, 0);
8767                                 // then apply the texture to it
8768                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8769                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8770                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8771                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8772                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8773                                 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);
8774                         }
8775                         else
8776                         {
8777                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
8778                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8779                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8780                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8781                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8782                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8783                                         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);
8784                                 else
8785                                         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);
8786                         }
8787                         break;
8788                 case TEXTURELAYERTYPE_TEXTURE:
8789                         // singletexture unlit texture with transparency support
8790                         R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8791                         R_Mesh_TexMatrix(0, &layer->texmatrix);
8792                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8793                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8794                         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);
8795                         break;
8796                 case TEXTURELAYERTYPE_FOG:
8797                         // singletexture fogging
8798                         if (layer->texture)
8799                         {
8800                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8801                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8802                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8803                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8804                         }
8805                         else
8806                         {
8807                                 R_Mesh_TexBind(0, 0);
8808                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8809                         }
8810                         // generate a color array for the fog pass
8811                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8812                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8813                         {
8814                                 int i;
8815                                 float f;
8816                                 const float *v;
8817                                 float *c;
8818                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8819                                 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)
8820                                 {
8821                                         f = 1 - RSurf_FogVertex(v);
8822                                         c[0] = layer->color[0];
8823                                         c[1] = layer->color[1];
8824                                         c[2] = layer->color[2];
8825                                         c[3] = f * layer->color[3];
8826                                 }
8827                         }
8828                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8829                         break;
8830                 default:
8831                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8832                 }
8833                 GL_LockArrays(0, 0);
8834         }
8835         CHECKGLERROR
8836         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8837         {
8838                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8839                 GL_AlphaTest(false);
8840         }
8841 }
8842
8843 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8844 {
8845         float c[4];
8846
8847         GL_AlphaTest(false);
8848         R_Mesh_ColorPointer(NULL, 0, 0);
8849         R_Mesh_ResetTextureState();
8850         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8851
8852         if(rsurface.texture && rsurface.texture->currentskinframe)
8853         {
8854                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8855                 c[3] *= rsurface.texture->currentalpha;
8856         }
8857         else
8858         {
8859                 c[0] = 1;
8860                 c[1] = 0;
8861                 c[2] = 1;
8862                 c[3] = 1;
8863         }
8864
8865         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
8866         {
8867                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8868                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8869                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8870         }
8871
8872         // brighten it up (as texture value 127 means "unlit")
8873         c[0] *= 2 * r_refdef.view.colorscale;
8874         c[1] *= 2 * r_refdef.view.colorscale;
8875         c[2] *= 2 * r_refdef.view.colorscale;
8876
8877         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8878                 c[3] *= r_wateralpha.value;
8879
8880         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8881         {
8882                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8883                 GL_DepthMask(false);
8884         }
8885         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8886         {
8887                 GL_BlendFunc(GL_ONE, GL_ONE);
8888                 GL_DepthMask(false);
8889         }
8890         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8891         {
8892                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8893                 GL_DepthMask(false);
8894         }
8895         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8896         {
8897                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8898                 GL_DepthMask(false);
8899         }
8900         else
8901         {
8902                 GL_BlendFunc(GL_ONE, GL_ZERO);
8903                 GL_DepthMask(writedepth);
8904         }
8905
8906         rsurface.lightmapcolor4f = NULL;
8907
8908         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8909         {
8910                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8911
8912                 rsurface.lightmapcolor4f = NULL;
8913                 rsurface.lightmapcolor4f_bufferobject = 0;
8914                 rsurface.lightmapcolor4f_bufferoffset = 0;
8915         }
8916         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8917         {
8918                 qboolean applycolor = true;
8919                 float one = 1.0;
8920
8921                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8922
8923                 r_refdef.lightmapintensity = 1;
8924                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8925                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8926         }
8927         else
8928         {
8929                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8930
8931                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8932                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8933                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8934         }
8935
8936         if(!rsurface.lightmapcolor4f)
8937                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8938
8939         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8940         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8941         if(r_refdef.fogenabled)
8942                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8943
8944         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8945         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8946 }
8947
8948 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8949 {
8950         CHECKGLERROR
8951         RSurf_SetupDepthAndCulling();
8952         if (r_showsurfaces.integer == 3 && !prepass)
8953         {
8954                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8955                 return;
8956         }
8957         switch (vid.renderpath)
8958         {
8959         case RENDERPATH_GL20:
8960         case RENDERPATH_CGGL:
8961                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8962                 break;
8963         case RENDERPATH_GL13:
8964                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8965                 break;
8966         case RENDERPATH_GL11:
8967                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8968                 break;
8969         }
8970         CHECKGLERROR
8971 }
8972
8973 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8974 {
8975         CHECKGLERROR
8976         RSurf_SetupDepthAndCulling();
8977         if (r_showsurfaces.integer == 3 && !prepass)
8978         {
8979                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8980                 return;
8981         }
8982         switch (vid.renderpath)
8983         {
8984         case RENDERPATH_GL20:
8985         case RENDERPATH_CGGL:
8986                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8987                 break;
8988         case RENDERPATH_GL13:
8989                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8990                 break;
8991         case RENDERPATH_GL11:
8992                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8993                 break;
8994         }
8995         CHECKGLERROR
8996 }
8997
8998 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8999 {
9000         int i, j;
9001         int texturenumsurfaces, endsurface;
9002         texture_t *texture;
9003         const msurface_t *surface;
9004         const msurface_t *texturesurfacelist[256];
9005
9006         // if the model is static it doesn't matter what value we give for
9007         // wantnormals and wanttangents, so this logic uses only rules applicable
9008         // to a model, knowing that they are meaningless otherwise
9009         if (ent == r_refdef.scene.worldentity)
9010                 RSurf_ActiveWorldEntity();
9011         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9012                 RSurf_ActiveModelEntity(ent, false, false, false);
9013         else
9014         {
9015                 switch (vid.renderpath)
9016                 {
9017                 case RENDERPATH_GL20:
9018                 case RENDERPATH_CGGL:
9019                         RSurf_ActiveModelEntity(ent, true, true, false);
9020                         break;
9021                 case RENDERPATH_GL13:
9022                 case RENDERPATH_GL11:
9023                         RSurf_ActiveModelEntity(ent, true, false, false);
9024                         break;
9025                 }
9026         }
9027
9028         if (r_transparentdepthmasking.integer)
9029         {
9030                 qboolean setup = false;
9031                 for (i = 0;i < numsurfaces;i = j)
9032                 {
9033                         j = i + 1;
9034                         surface = rsurface.modelsurfaces + surfacelist[i];
9035                         texture = surface->texture;
9036                         rsurface.texture = R_GetCurrentTexture(texture);
9037                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9038                         // scan ahead until we find a different texture
9039                         endsurface = min(i + 1024, numsurfaces);
9040                         texturenumsurfaces = 0;
9041                         texturesurfacelist[texturenumsurfaces++] = surface;
9042                         for (;j < endsurface;j++)
9043                         {
9044                                 surface = rsurface.modelsurfaces + surfacelist[j];
9045                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
9046                                         break;
9047                                 texturesurfacelist[texturenumsurfaces++] = surface;
9048                         }
9049                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9050                                 continue;
9051                         // render the range of surfaces as depth
9052                         if (!setup)
9053                         {
9054                                 setup = true;
9055                                 GL_ColorMask(0,0,0,0);
9056                                 GL_Color(1,1,1,1);
9057                                 GL_DepthTest(true);
9058                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9059                                 GL_DepthMask(true);
9060                                 GL_AlphaTest(false);
9061                                 R_Mesh_ColorPointer(NULL, 0, 0);
9062                                 R_Mesh_ResetTextureState();
9063                                 R_SetupShader_DepthOrShadow();
9064                         }
9065                         RSurf_SetupDepthAndCulling();
9066                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9067                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9068                 }
9069                 if (setup)
9070                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9071         }
9072
9073         for (i = 0;i < numsurfaces;i = j)
9074         {
9075                 j = i + 1;
9076                 surface = rsurface.modelsurfaces + surfacelist[i];
9077                 texture = surface->texture;
9078                 rsurface.texture = R_GetCurrentTexture(texture);
9079                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9080                 // scan ahead until we find a different texture
9081                 endsurface = min(i + 1024, numsurfaces);
9082                 texturenumsurfaces = 0;
9083                 texturesurfacelist[texturenumsurfaces++] = surface;
9084                 for (;j < endsurface;j++)
9085                 {
9086                         surface = rsurface.modelsurfaces + surfacelist[j];
9087                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
9088                                 break;
9089                         texturesurfacelist[texturenumsurfaces++] = surface;
9090                 }
9091                 // render the range of surfaces
9092                 if (ent == r_refdef.scene.worldentity)
9093                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9094                 else
9095                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9096         }
9097         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9098         GL_AlphaTest(false);
9099 }
9100
9101 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9102 {
9103         // transparent surfaces get pushed off into the transparent queue
9104         int surfacelistindex;
9105         const msurface_t *surface;
9106         vec3_t tempcenter, center;
9107         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9108         {
9109                 surface = texturesurfacelist[surfacelistindex];
9110                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9111                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9112                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9113                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9114                 if (queueentity->transparent_offset) // transparent offset
9115                 {
9116                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9117                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9118                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9119                 }
9120                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9121         }
9122 }
9123
9124 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9125 {
9126         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9127         CHECKGLERROR
9128         if (depthonly)
9129         {
9130                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9131                         return;
9132                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9133                         return;
9134                 RSurf_SetupDepthAndCulling();
9135                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9136                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9137         }
9138         else if (prepass)
9139         {
9140                 if (!rsurface.texture->currentnumlayers)
9141                         return;
9142                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9143                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9144                 else
9145                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9146         }
9147         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
9148         {
9149                 RSurf_SetupDepthAndCulling();
9150                 GL_AlphaTest(false);
9151                 R_Mesh_ColorPointer(NULL, 0, 0);
9152                 R_Mesh_ResetTextureState();
9153                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9154                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9155                 GL_DepthMask(true);
9156                 GL_BlendFunc(GL_ONE, GL_ZERO);
9157                 GL_Color(0, 0, 0, 1);
9158                 GL_DepthTest(writedepth);
9159                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9160         }
9161         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
9162         {
9163                 RSurf_SetupDepthAndCulling();
9164                 GL_AlphaTest(false);
9165                 R_Mesh_ColorPointer(NULL, 0, 0);
9166                 R_Mesh_ResetTextureState();
9167                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9168                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9169                 GL_DepthMask(true);
9170                 GL_BlendFunc(GL_ONE, GL_ZERO);
9171                 GL_DepthTest(true);
9172                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
9173         }
9174         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
9175                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9176         else if (!rsurface.texture->currentnumlayers)
9177                 return;
9178         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9179         {
9180                 // in the deferred case, transparent surfaces were queued during prepass
9181                 if (!r_shadow_usingdeferredprepass)
9182                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9183         }
9184         else
9185         {
9186                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9187                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9188         }
9189         CHECKGLERROR
9190 }
9191
9192 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9193 {
9194         int i, j;
9195         texture_t *texture;
9196         // break the surface list down into batches by texture and use of lightmapping
9197         for (i = 0;i < numsurfaces;i = j)
9198         {
9199                 j = i + 1;
9200                 // texture is the base texture pointer, rsurface.texture is the
9201                 // current frame/skin the texture is directing us to use (for example
9202                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9203                 // use skin 1 instead)
9204                 texture = surfacelist[i]->texture;
9205                 rsurface.texture = R_GetCurrentTexture(texture);
9206                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
9207                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9208                 {
9209                         // if this texture is not the kind we want, skip ahead to the next one
9210                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9211                                 ;
9212                         continue;
9213                 }
9214                 // simply scan ahead until we find a different texture or lightmap state
9215                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
9216                         ;
9217                 // render the range of surfaces
9218                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
9219         }
9220 }
9221
9222 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
9223 {
9224         CHECKGLERROR
9225         if (depthonly)
9226         {
9227                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9228                         return;
9229                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9230                         return;
9231                 RSurf_SetupDepthAndCulling();
9232                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9233                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9234         }
9235         else if (prepass)
9236         {
9237                 if (!rsurface.texture->currentnumlayers)
9238                         return;
9239                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9240                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9241                 else
9242                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9243         }
9244         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
9245         {
9246                 RSurf_SetupDepthAndCulling();
9247                 GL_AlphaTest(false);
9248                 R_Mesh_ColorPointer(NULL, 0, 0);
9249                 R_Mesh_ResetTextureState();
9250                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9251                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9252                 GL_DepthMask(true);
9253                 GL_BlendFunc(GL_ONE, GL_ZERO);
9254                 GL_Color(0, 0, 0, 1);
9255                 GL_DepthTest(writedepth);
9256                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9257         }
9258         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9259         {
9260                 RSurf_SetupDepthAndCulling();
9261                 GL_AlphaTest(false);
9262                 R_Mesh_ColorPointer(NULL, 0, 0);
9263                 R_Mesh_ResetTextureState();
9264                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9265                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9266                 GL_DepthMask(true);
9267                 GL_BlendFunc(GL_ONE, GL_ZERO);
9268                 GL_DepthTest(true);
9269                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
9270         }
9271         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
9272                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9273         else if (!rsurface.texture->currentnumlayers)
9274                 return;
9275         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9276         {
9277                 // in the deferred case, transparent surfaces were queued during prepass
9278                 if (!r_shadow_usingdeferredprepass)
9279                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9280         }
9281         else
9282         {
9283                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9284                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9285         }
9286         CHECKGLERROR
9287 }
9288
9289 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9290 {
9291         int i, j;
9292         texture_t *texture;
9293         // break the surface list down into batches by texture and use of lightmapping
9294         for (i = 0;i < numsurfaces;i = j)
9295         {
9296                 j = i + 1;
9297                 // texture is the base texture pointer, rsurface.texture is the
9298                 // current frame/skin the texture is directing us to use (for example
9299                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9300                 // use skin 1 instead)
9301                 texture = surfacelist[i]->texture;
9302                 rsurface.texture = R_GetCurrentTexture(texture);
9303                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
9304                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9305                 {
9306                         // if this texture is not the kind we want, skip ahead to the next one
9307                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9308                                 ;
9309                         continue;
9310                 }
9311                 // simply scan ahead until we find a different texture or lightmap state
9312                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
9313                         ;
9314                 // render the range of surfaces
9315                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
9316         }
9317 }
9318
9319 float locboxvertex3f[6*4*3] =
9320 {
9321         1,0,1, 1,0,0, 1,1,0, 1,1,1,
9322         0,1,1, 0,1,0, 0,0,0, 0,0,1,
9323         1,1,1, 1,1,0, 0,1,0, 0,1,1,
9324         0,0,1, 0,0,0, 1,0,0, 1,0,1,
9325         0,0,1, 1,0,1, 1,1,1, 0,1,1,
9326         1,0,0, 0,0,0, 0,1,0, 1,1,0
9327 };
9328
9329 unsigned short locboxelements[6*2*3] =
9330 {
9331          0, 1, 2, 0, 2, 3,
9332          4, 5, 6, 4, 6, 7,
9333          8, 9,10, 8,10,11,
9334         12,13,14, 12,14,15,
9335         16,17,18, 16,18,19,
9336         20,21,22, 20,22,23
9337 };
9338
9339 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9340 {
9341         int i, j;
9342         cl_locnode_t *loc = (cl_locnode_t *)ent;
9343         vec3_t mins, size;
9344         float vertex3f[6*4*3];
9345         CHECKGLERROR
9346         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9347         GL_DepthMask(false);
9348         GL_DepthRange(0, 1);
9349         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9350         GL_DepthTest(true);
9351         GL_CullFace(GL_NONE);
9352         R_EntityMatrix(&identitymatrix);
9353
9354         R_Mesh_VertexPointer(vertex3f, 0, 0);
9355         R_Mesh_ColorPointer(NULL, 0, 0);
9356         R_Mesh_ResetTextureState();
9357         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9358
9359         i = surfacelist[0];
9360         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9361                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9362                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9363                         surfacelist[0] < 0 ? 0.5f : 0.125f);
9364
9365         if (VectorCompare(loc->mins, loc->maxs))
9366         {
9367                 VectorSet(size, 2, 2, 2);
9368                 VectorMA(loc->mins, -0.5f, size, mins);
9369         }
9370         else
9371         {
9372                 VectorCopy(loc->mins, mins);
9373                 VectorSubtract(loc->maxs, loc->mins, size);
9374         }
9375
9376         for (i = 0;i < 6*4*3;)
9377                 for (j = 0;j < 3;j++, i++)
9378                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
9379
9380         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
9381 }
9382
9383 void R_DrawLocs(void)
9384 {
9385         int index;
9386         cl_locnode_t *loc, *nearestloc;
9387         vec3_t center;
9388         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
9389         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
9390         {
9391                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
9392                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
9393         }
9394 }
9395
9396 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
9397 {
9398         if (decalsystem->decals)
9399                 Mem_Free(decalsystem->decals);
9400         memset(decalsystem, 0, sizeof(*decalsystem));
9401 }
9402
9403 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)
9404 {
9405         tridecal_t *decal;
9406         tridecal_t *decals;
9407         int i;
9408         int maxdecals;
9409
9410         // expand or initialize the system
9411         if (decalsystem->maxdecals <= decalsystem->numdecals)
9412         {
9413                 decalsystem_t old = *decalsystem;
9414                 qboolean useshortelements;
9415                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
9416                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
9417                 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)));
9418                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
9419                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
9420                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
9421                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
9422                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
9423                 if (decalsystem->numdecals)
9424                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
9425                 if (old.decals)
9426                         Mem_Free(old.decals);
9427                 for (i = 0;i < decalsystem->maxdecals*3;i++)
9428                         decalsystem->element3i[i] = i;
9429                 if (useshortelements)
9430                         for (i = 0;i < decalsystem->maxdecals*3;i++)
9431                                 decalsystem->element3s[i] = i;
9432         }
9433
9434         // grab a decal and search for another free slot for the next one
9435         maxdecals = decalsystem->maxdecals;
9436         decals = decalsystem->decals;
9437         decal = decalsystem->decals + (i = decalsystem->freedecal++);
9438         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
9439                 ;
9440         decalsystem->freedecal = i;
9441         if (decalsystem->numdecals <= i)
9442                 decalsystem->numdecals = i + 1;
9443
9444         // initialize the decal
9445         decal->lived = 0;
9446         decal->triangleindex = triangleindex;
9447         decal->surfaceindex = surfaceindex;
9448         decal->decalsequence = decalsequence;
9449         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
9450         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
9451         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
9452         decal->color4ub[0][3] = 255;
9453         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
9454         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
9455         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
9456         decal->color4ub[1][3] = 255;
9457         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
9458         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
9459         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
9460         decal->color4ub[2][3] = 255;
9461         decal->vertex3f[0][0] = v0[0];
9462         decal->vertex3f[0][1] = v0[1];
9463         decal->vertex3f[0][2] = v0[2];
9464         decal->vertex3f[1][0] = v1[0];
9465         decal->vertex3f[1][1] = v1[1];
9466         decal->vertex3f[1][2] = v1[2];
9467         decal->vertex3f[2][0] = v2[0];
9468         decal->vertex3f[2][1] = v2[1];
9469         decal->vertex3f[2][2] = v2[2];
9470         decal->texcoord2f[0][0] = t0[0];
9471         decal->texcoord2f[0][1] = t0[1];
9472         decal->texcoord2f[1][0] = t1[0];
9473         decal->texcoord2f[1][1] = t1[1];
9474         decal->texcoord2f[2][0] = t2[0];
9475         decal->texcoord2f[2][1] = t2[1];
9476 }
9477
9478 extern cvar_t cl_decals_bias;
9479 extern cvar_t cl_decals_models;
9480 extern cvar_t cl_decals_newsystem_intensitymultiplier;
9481 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)
9482 {
9483         matrix4x4_t projection;
9484         decalsystem_t *decalsystem;
9485         qboolean dynamic;
9486         dp_model_t *model;
9487         const float *vertex3f;
9488         const msurface_t *surface;
9489         const msurface_t *surfaces;
9490         const int *surfacelist;
9491         const texture_t *texture;
9492         int numvertices;
9493         int numtriangles;
9494         int numsurfacelist;
9495         int surfacelistindex;
9496         int surfaceindex;
9497         int triangleindex;
9498         int decalsurfaceindex;
9499         int cornerindex;
9500         int index;
9501         int numpoints;
9502         const int *e;
9503         float localorigin[3];
9504         float localnormal[3];
9505         float localmins[3];
9506         float localmaxs[3];
9507         float localsize;
9508         float ilocalsize;
9509         float v[9][3];
9510         float tc[9][2];
9511         float c[9][4];
9512         //float normal[3];
9513         float planes[6][4];
9514         float f;
9515         float points[2][9][3];
9516         float angles[3];
9517         float temp[3];
9518
9519         decalsystem = &ent->decalsystem;
9520         model = ent->model;
9521         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
9522         {
9523                 R_DecalSystem_Reset(&ent->decalsystem);
9524                 return;
9525         }
9526
9527         if (!model->brush.data_nodes && !cl_decals_models.integer)
9528         {
9529                 if (decalsystem->model)
9530                         R_DecalSystem_Reset(decalsystem);
9531                 return;
9532         }
9533
9534         if (decalsystem->model != model)
9535                 R_DecalSystem_Reset(decalsystem);
9536         decalsystem->model = model;
9537
9538         RSurf_ActiveModelEntity(ent, false, false, false);
9539
9540         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
9541         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
9542         VectorNormalize(localnormal);
9543         localsize = worldsize*rsurface.inversematrixscale;
9544         ilocalsize = 1.0f / localsize;
9545         localmins[0] = localorigin[0] - localsize;
9546         localmins[1] = localorigin[1] - localsize;
9547         localmins[2] = localorigin[2] - localsize;
9548         localmaxs[0] = localorigin[0] + localsize;
9549         localmaxs[1] = localorigin[1] + localsize;
9550         localmaxs[2] = localorigin[2] + localsize;
9551
9552         //VectorCopy(localnormal, planes[4]);
9553         //VectorVectors(planes[4], planes[2], planes[0]);
9554         AnglesFromVectors(angles, localnormal, NULL, false);
9555         AngleVectors(angles, planes[0], planes[2], planes[4]);
9556         VectorNegate(planes[0], planes[1]);
9557         VectorNegate(planes[2], planes[3]);
9558         VectorNegate(planes[4], planes[5]);
9559         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
9560         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
9561         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
9562         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
9563         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
9564         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
9565
9566 #if 1
9567 // works
9568 {
9569         matrix4x4_t forwardprojection;
9570         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
9571         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
9572 }
9573 #else
9574 // broken
9575 {
9576         float projectionvector[4][3];
9577         VectorScale(planes[0], ilocalsize, projectionvector[0]);
9578         VectorScale(planes[2], ilocalsize, projectionvector[1]);
9579         VectorScale(planes[4], ilocalsize, projectionvector[2]);
9580         projectionvector[0][0] = planes[0][0] * ilocalsize;
9581         projectionvector[0][1] = planes[1][0] * ilocalsize;
9582         projectionvector[0][2] = planes[2][0] * ilocalsize;
9583         projectionvector[1][0] = planes[0][1] * ilocalsize;
9584         projectionvector[1][1] = planes[1][1] * ilocalsize;
9585         projectionvector[1][2] = planes[2][1] * ilocalsize;
9586         projectionvector[2][0] = planes[0][2] * ilocalsize;
9587         projectionvector[2][1] = planes[1][2] * ilocalsize;
9588         projectionvector[2][2] = planes[2][2] * ilocalsize;
9589         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
9590         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
9591         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
9592         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
9593 }
9594 #endif
9595
9596         dynamic = model->surfmesh.isanimated;
9597         vertex3f = rsurface.modelvertex3f;
9598         numsurfacelist = model->nummodelsurfaces;
9599         surfacelist = model->sortedmodelsurfaces;
9600         surfaces = model->data_surfaces;
9601         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
9602         {
9603                 surfaceindex = surfacelist[surfacelistindex];
9604                 surface = surfaces + surfaceindex;
9605                 // skip transparent surfaces
9606                 texture = surface->texture;
9607                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9608                         continue;
9609                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
9610                         continue;
9611                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
9612                         continue;
9613                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
9614                 numvertices = surface->num_vertices;
9615                 numtriangles = surface->num_triangles;
9616                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
9617                 {
9618                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
9619                         {
9620                                 index = 3*e[cornerindex];
9621                                 VectorCopy(vertex3f + index, v[cornerindex]);
9622                         }
9623                         // cull backfaces
9624                         //TriangleNormal(v[0], v[1], v[2], normal);
9625                         //if (DotProduct(normal, localnormal) < 0.0f)
9626                         //      continue;
9627                         // clip by each of the box planes formed from the projection matrix
9628                         // if anything survives, we emit the decal
9629                         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]);
9630                         if (numpoints < 3)
9631                                 continue;
9632                         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]);
9633                         if (numpoints < 3)
9634                                 continue;
9635                         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]);
9636                         if (numpoints < 3)
9637                                 continue;
9638                         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]);
9639                         if (numpoints < 3)
9640                                 continue;
9641                         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]);
9642                         if (numpoints < 3)
9643                                 continue;
9644                         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]);
9645                         if (numpoints < 3)
9646                                 continue;
9647                         // some part of the triangle survived, so we have to accept it...
9648                         if (dynamic)
9649                         {
9650                                 // dynamic always uses the original triangle
9651                                 numpoints = 3;
9652                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9653                                 {
9654                                         index = 3*e[cornerindex];
9655                                         VectorCopy(vertex3f + index, v[cornerindex]);
9656                                 }
9657                         }
9658                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
9659                         {
9660                                 // convert vertex positions to texcoords
9661                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
9662                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
9663                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
9664                                 // calculate distance fade from the projection origin
9665                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
9666                                 f = bound(0.0f, f, 1.0f);
9667                                 c[cornerindex][0] = r * f;
9668                                 c[cornerindex][1] = g * f;
9669                                 c[cornerindex][2] = b * f;
9670                                 c[cornerindex][3] = 1.0f;
9671                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
9672                         }
9673                         if (dynamic)
9674                                 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);
9675                         else
9676                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
9677                                         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);
9678                 }
9679         }
9680 }
9681
9682 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
9683 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)
9684 {
9685         int renderentityindex;
9686         float worldmins[3];
9687         float worldmaxs[3];
9688         entity_render_t *ent;
9689
9690         if (!cl_decals_newsystem.integer)
9691                 return;
9692
9693         worldmins[0] = worldorigin[0] - worldsize;
9694         worldmins[1] = worldorigin[1] - worldsize;
9695         worldmins[2] = worldorigin[2] - worldsize;
9696         worldmaxs[0] = worldorigin[0] + worldsize;
9697         worldmaxs[1] = worldorigin[1] + worldsize;
9698         worldmaxs[2] = worldorigin[2] + worldsize;
9699
9700         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9701
9702         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
9703         {
9704                 ent = r_refdef.scene.entities[renderentityindex];
9705                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
9706                         continue;
9707
9708                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9709         }
9710 }
9711
9712 typedef struct r_decalsystem_splatqueue_s
9713 {
9714         vec3_t worldorigin;
9715         vec3_t worldnormal;
9716         float color[4];
9717         float tcrange[4];
9718         float worldsize;
9719         int decalsequence;
9720 }
9721 r_decalsystem_splatqueue_t;
9722
9723 int r_decalsystem_numqueued = 0;
9724 #define MAX_DECALSYSTEM_QUEUE 1024
9725 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
9726
9727 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)
9728 {
9729         r_decalsystem_splatqueue_t *queue;
9730
9731         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
9732                 return;
9733
9734         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
9735         VectorCopy(worldorigin, queue->worldorigin);
9736         VectorCopy(worldnormal, queue->worldnormal);
9737         Vector4Set(queue->color, r, g, b, a);
9738         Vector4Set(queue->tcrange, s1, t1, s2, t2);
9739         queue->worldsize = worldsize;
9740         queue->decalsequence = cl.decalsequence++;
9741 }
9742
9743 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
9744 {
9745         int i;
9746         r_decalsystem_splatqueue_t *queue;
9747
9748         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
9749                 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);
9750         r_decalsystem_numqueued = 0;
9751 }
9752
9753 extern cvar_t cl_decals_max;
9754 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
9755 {
9756         int i;
9757         decalsystem_t *decalsystem = &ent->decalsystem;
9758         int numdecals;
9759         int killsequence;
9760         tridecal_t *decal;
9761         float frametime;
9762         float lifetime;
9763
9764         if (!decalsystem->numdecals)
9765                 return;
9766
9767         if (r_showsurfaces.integer)
9768                 return;
9769
9770         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9771         {
9772                 R_DecalSystem_Reset(decalsystem);
9773                 return;
9774         }
9775
9776         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
9777         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
9778
9779         if (decalsystem->lastupdatetime)
9780                 frametime = (cl.time - decalsystem->lastupdatetime);
9781         else
9782                 frametime = 0;
9783         decalsystem->lastupdatetime = cl.time;
9784         decal = decalsystem->decals;
9785         numdecals = decalsystem->numdecals;
9786
9787         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9788         {
9789                 if (decal->color4ub[0][3])
9790                 {
9791                         decal->lived += frametime;
9792                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
9793                         {
9794                                 memset(decal, 0, sizeof(*decal));
9795                                 if (decalsystem->freedecal > i)
9796                                         decalsystem->freedecal = i;
9797                         }
9798                 }
9799         }
9800         decal = decalsystem->decals;
9801         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
9802                 numdecals--;
9803
9804         // collapse the array by shuffling the tail decals into the gaps
9805         for (;;)
9806         {
9807                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
9808                         decalsystem->freedecal++;
9809                 if (decalsystem->freedecal == numdecals)
9810                         break;
9811                 decal[decalsystem->freedecal] = decal[--numdecals];
9812         }
9813
9814         decalsystem->numdecals = numdecals;
9815
9816         if (numdecals <= 0)
9817         {
9818                 // if there are no decals left, reset decalsystem
9819                 R_DecalSystem_Reset(decalsystem);
9820         }
9821 }
9822
9823 extern skinframe_t *decalskinframe;
9824 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9825 {
9826         int i;
9827         decalsystem_t *decalsystem = &ent->decalsystem;
9828         int numdecals;
9829         tridecal_t *decal;
9830         float fadedelay;
9831         float faderate;
9832         float alpha;
9833         float *v3f;
9834         float *c4f;
9835         float *t2f;
9836         const int *e;
9837         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9838         int numtris = 0;
9839
9840         numdecals = decalsystem->numdecals;
9841         if (!numdecals)
9842                 return;
9843
9844         if (r_showsurfaces.integer)
9845                 return;
9846
9847         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9848         {
9849                 R_DecalSystem_Reset(decalsystem);
9850                 return;
9851         }
9852
9853         // if the model is static it doesn't matter what value we give for
9854         // wantnormals and wanttangents, so this logic uses only rules applicable
9855         // to a model, knowing that they are meaningless otherwise
9856         if (ent == r_refdef.scene.worldentity)
9857                 RSurf_ActiveWorldEntity();
9858         else
9859                 RSurf_ActiveModelEntity(ent, false, false, false);
9860
9861         decalsystem->lastupdatetime = cl.time;
9862         decal = decalsystem->decals;
9863
9864         fadedelay = cl_decals_time.value;
9865         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9866
9867         // update vertex positions for animated models
9868         v3f = decalsystem->vertex3f;
9869         c4f = decalsystem->color4f;
9870         t2f = decalsystem->texcoord2f;
9871         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9872         {
9873                 if (!decal->color4ub[0][3])
9874                         continue;
9875
9876                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9877                         continue;
9878
9879                 // update color values for fading decals
9880                 if (decal->lived >= cl_decals_time.value)
9881                 {
9882                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9883                         alpha *= (1.0f/255.0f);
9884                 }
9885                 else
9886                         alpha = 1.0f/255.0f;
9887
9888                 c4f[ 0] = decal->color4ub[0][0] * alpha;
9889                 c4f[ 1] = decal->color4ub[0][1] * alpha;
9890                 c4f[ 2] = decal->color4ub[0][2] * alpha;
9891                 c4f[ 3] = 1;
9892                 c4f[ 4] = decal->color4ub[1][0] * alpha;
9893                 c4f[ 5] = decal->color4ub[1][1] * alpha;
9894                 c4f[ 6] = decal->color4ub[1][2] * alpha;
9895                 c4f[ 7] = 1;
9896                 c4f[ 8] = decal->color4ub[2][0] * alpha;
9897                 c4f[ 9] = decal->color4ub[2][1] * alpha;
9898                 c4f[10] = decal->color4ub[2][2] * alpha;
9899                 c4f[11] = 1;
9900
9901                 t2f[0] = decal->texcoord2f[0][0];
9902                 t2f[1] = decal->texcoord2f[0][1];
9903                 t2f[2] = decal->texcoord2f[1][0];
9904                 t2f[3] = decal->texcoord2f[1][1];
9905                 t2f[4] = decal->texcoord2f[2][0];
9906                 t2f[5] = decal->texcoord2f[2][1];
9907
9908                 // update vertex positions for animated models
9909                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9910                 {
9911                         e = rsurface.modelelement3i + 3*decal->triangleindex;
9912                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9913                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9914                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9915                 }
9916                 else
9917                 {
9918                         VectorCopy(decal->vertex3f[0], v3f);
9919                         VectorCopy(decal->vertex3f[1], v3f + 3);
9920                         VectorCopy(decal->vertex3f[2], v3f + 6);
9921                 }
9922
9923                 v3f += 9;
9924                 c4f += 12;
9925                 t2f += 6;
9926                 numtris++;
9927         }
9928
9929         if (numtris > 0)
9930         {
9931                 r_refdef.stats.drawndecals += numtris;
9932
9933                 if (r_refdef.fogenabled)
9934                 {
9935                         switch(vid.renderpath)
9936                         {
9937                         case RENDERPATH_GL20:
9938                         case RENDERPATH_CGGL:
9939                         case RENDERPATH_GL13:
9940                         case RENDERPATH_GL11:
9941                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
9942                                 {
9943                                         alpha = RSurf_FogVertex(v3f);
9944                                         c4f[0] *= alpha;
9945                                         c4f[1] *= alpha;
9946                                         c4f[2] *= alpha;
9947                                 }
9948                                 break;
9949                         }
9950                 }
9951
9952                 // now render the decals all at once
9953                 // (this assumes they all use one particle font texture!)
9954                 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);
9955                 R_Mesh_ResetTextureState();
9956                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9957                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9958                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9959                 GL_DepthMask(false);
9960                 GL_DepthRange(0, 1);
9961                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9962                 GL_DepthTest(true);
9963                 GL_CullFace(GL_NONE);
9964                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9965                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
9966                 GL_LockArrays(0, numtris * 3);
9967                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9968                 GL_LockArrays(0, 0);
9969         }
9970 }
9971
9972 static void R_DrawModelDecals(void)
9973 {
9974         int i, numdecals;
9975
9976         // fade faster when there are too many decals
9977         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9978         for (i = 0;i < r_refdef.scene.numentities;i++)
9979                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9980
9981         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9982         for (i = 0;i < r_refdef.scene.numentities;i++)
9983                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9984                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9985
9986         R_DecalSystem_ApplySplatEntitiesQueue();
9987
9988         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9989         for (i = 0;i < r_refdef.scene.numentities;i++)
9990                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9991
9992         r_refdef.stats.totaldecals += numdecals;
9993
9994         if (r_showsurfaces.integer)
9995                 return;
9996
9997         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9998
9999         for (i = 0;i < r_refdef.scene.numentities;i++)
10000         {
10001                 if (!r_refdef.viewcache.entityvisible[i])
10002                         continue;
10003                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10004                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10005         }
10006 }
10007
10008 void R_DrawDebugModel(void)
10009 {
10010         entity_render_t *ent = rsurface.entity;
10011         int i, j, k, l, flagsmask;
10012         const int *elements;
10013         q3mbrush_t *brush;
10014         const msurface_t *surface;
10015         dp_model_t *model = ent->model;
10016         vec3_t v;
10017
10018         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10019
10020         R_Mesh_ColorPointer(NULL, 0, 0);
10021         R_Mesh_ResetTextureState();
10022         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10023         GL_DepthRange(0, 1);
10024         GL_DepthTest(!r_showdisabledepthtest.integer);
10025         GL_DepthMask(false);
10026         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10027
10028         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
10029         {
10030                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10031                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
10032                 {
10033                         if (brush->colbrushf && brush->colbrushf->numtriangles)
10034                         {
10035                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
10036                                 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);
10037                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
10038                         }
10039                 }
10040                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
10041                 {
10042                         if (surface->num_collisiontriangles)
10043                         {
10044                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
10045                                 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);
10046                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
10047                         }
10048                 }
10049         }
10050
10051         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10052
10053         if (r_showtris.integer || r_shownormals.integer)
10054         {
10055                 if (r_showdisabledepthtest.integer)
10056                 {
10057                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10058                         GL_DepthMask(false);
10059                 }
10060                 else
10061                 {
10062                         GL_BlendFunc(GL_ONE, GL_ZERO);
10063                         GL_DepthMask(true);
10064                 }
10065                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10066                 {
10067                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10068                                 continue;
10069                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10070                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10071                         {
10072                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
10073                                 if (r_showtris.value > 0)
10074                                 {
10075                                         if (!rsurface.texture->currentlayers->depthmask)
10076                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10077                                         else if (ent == r_refdef.scene.worldentity)
10078                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10079                                         else
10080                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10081                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
10082                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
10083                                         R_Mesh_ColorPointer(NULL, 0, 0);
10084                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
10085                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10086                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
10087                                         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);
10088                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10089                                         CHECKGLERROR
10090                                 }
10091                                 if (r_shownormals.value < 0)
10092                                 {
10093                                         qglBegin(GL_LINES);
10094                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10095                                         {
10096                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10097                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10098                                                 qglVertex3f(v[0], v[1], v[2]);
10099                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
10100                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10101                                                 qglVertex3f(v[0], v[1], v[2]);
10102                                         }
10103                                         qglEnd();
10104                                         CHECKGLERROR
10105                                 }
10106                                 if (r_shownormals.value > 0)
10107                                 {
10108                                         qglBegin(GL_LINES);
10109                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10110                                         {
10111                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10112                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10113                                                 qglVertex3f(v[0], v[1], v[2]);
10114                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
10115                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10116                                                 qglVertex3f(v[0], v[1], v[2]);
10117                                         }
10118                                         qglEnd();
10119                                         CHECKGLERROR
10120                                         qglBegin(GL_LINES);
10121                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10122                                         {
10123                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10124                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10125                                                 qglVertex3f(v[0], v[1], v[2]);
10126                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
10127                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10128                                                 qglVertex3f(v[0], v[1], v[2]);
10129                                         }
10130                                         qglEnd();
10131                                         CHECKGLERROR
10132                                         qglBegin(GL_LINES);
10133                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10134                                         {
10135                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10136                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10137                                                 qglVertex3f(v[0], v[1], v[2]);
10138                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
10139                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10140                                                 qglVertex3f(v[0], v[1], v[2]);
10141                                         }
10142                                         qglEnd();
10143                                         CHECKGLERROR
10144                                 }
10145                         }
10146                 }
10147                 rsurface.texture = NULL;
10148         }
10149 }
10150
10151 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10152 int r_maxsurfacelist = 0;
10153 const msurface_t **r_surfacelist = NULL;
10154 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10155 {
10156         int i, j, endj, f, flagsmask;
10157         texture_t *t;
10158         dp_model_t *model = r_refdef.scene.worldmodel;
10159         msurface_t *surfaces;
10160         unsigned char *update;
10161         int numsurfacelist = 0;
10162         if (model == NULL)
10163                 return;
10164
10165         if (r_maxsurfacelist < model->num_surfaces)
10166         {
10167                 r_maxsurfacelist = model->num_surfaces;
10168                 if (r_surfacelist)
10169                         Mem_Free((msurface_t**)r_surfacelist);
10170                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10171         }
10172
10173         RSurf_ActiveWorldEntity();
10174
10175         surfaces = model->data_surfaces;
10176         update = model->brushq1.lightmapupdateflags;
10177
10178         // update light styles on this submodel
10179         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
10180         {
10181                 model_brush_lightstyleinfo_t *style;
10182                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10183                 {
10184                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
10185                         {
10186                                 int *list = style->surfacelist;
10187                                 style->value = r_refdef.scene.lightstylevalue[style->style];
10188                                 for (j = 0;j < style->numsurfaces;j++)
10189                                         update[list[j]] = true;
10190                         }
10191                 }
10192         }
10193
10194         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10195
10196         if (debug)
10197         {
10198                 R_DrawDebugModel();
10199                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10200                 return;
10201         }
10202
10203         f = 0;
10204         t = NULL;
10205         rsurface.uselightmaptexture = false;
10206         rsurface.texture = NULL;
10207         rsurface.rtlight = NULL;
10208         numsurfacelist = 0;
10209         // add visible surfaces to draw list
10210         for (i = 0;i < model->nummodelsurfaces;i++)
10211         {
10212                 j = model->sortedmodelsurfaces[i];
10213                 if (r_refdef.viewcache.world_surfacevisible[j])
10214                         r_surfacelist[numsurfacelist++] = surfaces + j;
10215         }
10216         // update lightmaps if needed
10217         if (update)
10218         {
10219                 int updated = 0;
10220                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10221                 {
10222                         if (r_refdef.viewcache.world_surfacevisible[j])
10223                         {
10224                                 if (update[j])
10225                                 {
10226                                         updated++;
10227                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
10228                                 }
10229                         }
10230                 }
10231                 if (updated)
10232                 {
10233                         int count = model->brushq3.num_mergedlightmaps;
10234                         for (i = 0;i < count;i++)
10235                         {
10236                                 if (model->brushq3.data_deluxemaps[i])
10237                                         R_FlushTexture(model->brushq3.data_deluxemaps[i]);
10238                                 if (model->brushq3.data_lightmaps[i])
10239                                         R_FlushTexture(model->brushq3.data_lightmaps[i]);
10240                         }
10241                 }
10242         }
10243         // don't do anything if there were no surfaces
10244         if (!numsurfacelist)
10245         {
10246                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10247                 return;
10248         }
10249         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
10250         GL_AlphaTest(false);
10251
10252         // add to stats if desired
10253         if (r_speeds.integer && !skysurfaces && !depthonly)
10254         {
10255                 r_refdef.stats.world_surfaces += numsurfacelist;
10256                 for (j = 0;j < numsurfacelist;j++)
10257                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
10258         }
10259
10260         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10261 }
10262
10263 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10264 {
10265         int i, j, endj, f, flagsmask;
10266         texture_t *t;
10267         dp_model_t *model = ent->model;
10268         msurface_t *surfaces;
10269         unsigned char *update;
10270         int numsurfacelist = 0;
10271         if (model == NULL)
10272                 return;
10273
10274         if (r_maxsurfacelist < model->num_surfaces)
10275         {
10276                 r_maxsurfacelist = model->num_surfaces;
10277                 if (r_surfacelist)
10278                         Mem_Free((msurface_t **)r_surfacelist);
10279                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10280         }
10281
10282         // if the model is static it doesn't matter what value we give for
10283         // wantnormals and wanttangents, so this logic uses only rules applicable
10284         // to a model, knowing that they are meaningless otherwise
10285         if (ent == r_refdef.scene.worldentity)
10286                 RSurf_ActiveWorldEntity();
10287         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10288                 RSurf_ActiveModelEntity(ent, false, false, false);
10289         else if (prepass)
10290                 RSurf_ActiveModelEntity(ent, true, true, true);
10291         else if (depthonly)
10292                 RSurf_ActiveModelEntity(ent, false, false, false);
10293         else
10294         {
10295                 switch (vid.renderpath)
10296                 {
10297                 case RENDERPATH_GL20:
10298                 case RENDERPATH_CGGL:
10299                         RSurf_ActiveModelEntity(ent, true, true, false);
10300                         break;
10301                 case RENDERPATH_GL13:
10302                 case RENDERPATH_GL11:
10303                         RSurf_ActiveModelEntity(ent, true, false, false);
10304                         break;
10305                 }
10306         }
10307
10308         surfaces = model->data_surfaces;
10309         update = model->brushq1.lightmapupdateflags;
10310
10311         // update light styles
10312         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
10313         {
10314                 model_brush_lightstyleinfo_t *style;
10315                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10316                 {
10317                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
10318                         {
10319                                 int *list = style->surfacelist;
10320                                 style->value = r_refdef.scene.lightstylevalue[style->style];
10321                                 for (j = 0;j < style->numsurfaces;j++)
10322                                         update[list[j]] = true;
10323                         }
10324                 }
10325         }
10326
10327         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10328
10329         if (debug)
10330         {
10331                 R_DrawDebugModel();
10332                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10333                 return;
10334         }
10335
10336         f = 0;
10337         t = NULL;
10338         rsurface.uselightmaptexture = false;
10339         rsurface.texture = NULL;
10340         rsurface.rtlight = NULL;
10341         numsurfacelist = 0;
10342         // add visible surfaces to draw list
10343         for (i = 0;i < model->nummodelsurfaces;i++)
10344                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
10345         // don't do anything if there were no surfaces
10346         if (!numsurfacelist)
10347         {
10348                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10349                 return;
10350         }
10351         // update lightmaps if needed
10352         if (update)
10353         {
10354                 int updated = 0;
10355                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10356                 {
10357                         if (update[j])
10358                         {
10359                                 updated++;
10360                                 R_BuildLightMap(ent, surfaces + j);
10361                         }
10362                 }
10363                 if (updated)
10364                 {
10365                         int count = model->brushq3.num_mergedlightmaps;
10366                         for (i = 0;i < count;i++)
10367                         {
10368                                 if (model->brushq3.data_deluxemaps[i])
10369                                         R_FlushTexture(model->brushq3.data_deluxemaps[i]);
10370                                 if (model->brushq3.data_lightmaps[i])
10371                                         R_FlushTexture(model->brushq3.data_lightmaps[i]);
10372                         }
10373                 }
10374         }
10375         if (update)
10376                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10377                         if (update[j])
10378                                 R_BuildLightMap(ent, surfaces + j);
10379         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
10380         GL_AlphaTest(false);
10381
10382         // add to stats if desired
10383         if (r_speeds.integer && !skysurfaces && !depthonly)
10384         {
10385                 r_refdef.stats.entities_surfaces += numsurfacelist;
10386                 for (j = 0;j < numsurfacelist;j++)
10387                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
10388         }
10389
10390         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10391 }
10392
10393 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
10394 {
10395         static texture_t texture;
10396         static msurface_t surface;
10397         const msurface_t *surfacelist = &surface;
10398
10399         // fake enough texture and surface state to render this geometry
10400
10401         texture.update_lastrenderframe = -1; // regenerate this texture
10402         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
10403         texture.currentskinframe = skinframe;
10404         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
10405         texture.specularscalemod = 1;
10406         texture.specularpowermod = 1;
10407
10408         surface.texture = &texture;
10409         surface.num_triangles = numtriangles;
10410         surface.num_firsttriangle = firsttriangle;
10411         surface.num_vertices = numvertices;
10412         surface.num_firstvertex = firstvertex;
10413
10414         // now render it
10415         rsurface.texture = R_GetCurrentTexture(surface.texture);
10416         rsurface.uselightmaptexture = false;
10417         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10418 }
10419
10420 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)
10421 {
10422         static msurface_t surface;
10423         const msurface_t *surfacelist = &surface;
10424
10425         // fake enough texture and surface state to render this geometry
10426
10427         surface.texture = texture;
10428         surface.num_triangles = numtriangles;
10429         surface.num_firsttriangle = firsttriangle;
10430         surface.num_vertices = numvertices;
10431         surface.num_firstvertex = firstvertex;
10432
10433         // now render it
10434         rsurface.texture = R_GetCurrentTexture(surface.texture);
10435         rsurface.uselightmaptexture = false;
10436         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10437 }