]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
merging master again
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_frame = 0; ///< used only by R_GetCurrentTexture
33
34 qboolean r_loadnormalmap;
35 qboolean r_loadgloss;
36 qboolean r_loadfog;
37
38 //
39 // screen size info
40 //
41 r_refdef_t r_refdef;
42
43 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
44 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
45 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
46 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
47 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
48 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
49 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
50 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
51
52 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
53 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
54 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
55 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
56 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
57
58 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
59 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
60 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
61 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
62 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
63 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
64 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
65 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
66 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
67 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
68 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
69 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
70 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
71 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
72 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
73 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
74 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
75 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
76 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
77 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
78 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
79 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
80 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
81 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
82 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
83 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
84 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
85 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
86 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
87 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
88 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
89 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
90 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
91 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
92 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
93 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
94 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
95 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
96 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
97 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
98 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
99 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
100
101 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
102 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
103 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
104 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
105 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
106 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
107 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
108 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
109
110 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
111 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
112 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
113
114 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
115 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
116 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
117 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
118 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
119 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
120 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
121 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
122 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
123
124 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
125 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
126 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
127 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
128 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
129
130 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
131 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
132 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
133 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
134
135 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
136 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
137 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
138 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
139 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
140 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
141 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
142
143 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
144 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
145 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
146 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
147
148 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
149
150 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
151
152 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
153
154 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
155 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
156 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
157 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
158 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
159 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
160 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
161
162 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
163
164 extern cvar_t v_glslgamma;
165
166 extern qboolean v_flipped_state;
167
168 static struct r_bloomstate_s
169 {
170         qboolean enabled;
171         qboolean hdr;
172
173         int bloomwidth, bloomheight;
174
175         int screentexturewidth, screentextureheight;
176         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
177
178         int bloomtexturewidth, bloomtextureheight;
179         rtexture_t *texture_bloom;
180
181         // arrays for rendering the screen passes
182         float screentexcoord2f[8];
183         float bloomtexcoord2f[8];
184         float offsettexcoord2f[8];
185
186         r_viewport_t viewport;
187 }
188 r_bloomstate;
189
190 r_waterstate_t r_waterstate;
191
192 /// shadow volume bsp struct with automatically growing nodes buffer
193 svbsp_t r_svbsp;
194
195 rtexture_t *r_texture_blanknormalmap;
196 rtexture_t *r_texture_white;
197 rtexture_t *r_texture_grey128;
198 rtexture_t *r_texture_black;
199 rtexture_t *r_texture_notexture;
200 rtexture_t *r_texture_whitecube;
201 rtexture_t *r_texture_normalizationcube;
202 rtexture_t *r_texture_fogattenuation;
203 rtexture_t *r_texture_gammaramps;
204 unsigned int r_texture_gammaramps_serial;
205 //rtexture_t *r_texture_fogintensity;
206
207 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
208 unsigned int r_numqueries;
209 unsigned int r_maxqueries;
210
211 typedef struct r_qwskincache_s
212 {
213         char name[MAX_QPATH];
214         skinframe_t *skinframe;
215 }
216 r_qwskincache_t;
217
218 static r_qwskincache_t *r_qwskincache;
219 static int r_qwskincache_size;
220
221 /// vertex coordinates for a quad that covers the screen exactly
222 const float r_screenvertex3f[12] =
223 {
224         0, 0, 0,
225         1, 0, 0,
226         1, 1, 0,
227         0, 1, 0
228 };
229
230 extern void R_DrawModelShadows(void);
231
232 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
233 {
234         int i;
235         for (i = 0;i < verts;i++)
236         {
237                 out[0] = in[0] * r;
238                 out[1] = in[1] * g;
239                 out[2] = in[2] * b;
240                 out[3] = in[3];
241                 in += 4;
242                 out += 4;
243         }
244 }
245
246 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
247 {
248         int i;
249         for (i = 0;i < verts;i++)
250         {
251                 out[0] = r;
252                 out[1] = g;
253                 out[2] = b;
254                 out[3] = a;
255                 out += 4;
256         }
257 }
258
259 // FIXME: move this to client?
260 void FOG_clear(void)
261 {
262         if (gamemode == GAME_NEHAHRA)
263         {
264                 Cvar_Set("gl_fogenable", "0");
265                 Cvar_Set("gl_fogdensity", "0.2");
266                 Cvar_Set("gl_fogred", "0.3");
267                 Cvar_Set("gl_foggreen", "0.3");
268                 Cvar_Set("gl_fogblue", "0.3");
269         }
270         r_refdef.fog_density = 0;
271         r_refdef.fog_red = 0;
272         r_refdef.fog_green = 0;
273         r_refdef.fog_blue = 0;
274         r_refdef.fog_alpha = 1;
275         r_refdef.fog_start = 0;
276         r_refdef.fog_end = 16384;
277         r_refdef.fog_height = 1<<30;
278         r_refdef.fog_fadedepth = 128;
279 }
280
281 static void R_BuildBlankTextures(void)
282 {
283         unsigned char data[4];
284         data[2] = 128; // normal X
285         data[1] = 128; // normal Y
286         data[0] = 255; // normal Z
287         data[3] = 128; // height
288         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
289         data[0] = 255;
290         data[1] = 255;
291         data[2] = 255;
292         data[3] = 255;
293         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
294         data[0] = 128;
295         data[1] = 128;
296         data[2] = 128;
297         data[3] = 255;
298         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
299         data[0] = 0;
300         data[1] = 0;
301         data[2] = 0;
302         data[3] = 255;
303         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
304 }
305
306 static void R_BuildNoTexture(void)
307 {
308         int x, y;
309         unsigned char pix[16][16][4];
310         // this makes a light grey/dark grey checkerboard texture
311         for (y = 0;y < 16;y++)
312         {
313                 for (x = 0;x < 16;x++)
314                 {
315                         if ((y < 8) ^ (x < 8))
316                         {
317                                 pix[y][x][0] = 128;
318                                 pix[y][x][1] = 128;
319                                 pix[y][x][2] = 128;
320                                 pix[y][x][3] = 255;
321                         }
322                         else
323                         {
324                                 pix[y][x][0] = 64;
325                                 pix[y][x][1] = 64;
326                                 pix[y][x][2] = 64;
327                                 pix[y][x][3] = 255;
328                         }
329                 }
330         }
331         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
332 }
333
334 static void R_BuildWhiteCube(void)
335 {
336         unsigned char data[6*1*1*4];
337         memset(data, 255, sizeof(data));
338         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
339 }
340
341 static void R_BuildNormalizationCube(void)
342 {
343         int x, y, side;
344         vec3_t v;
345         vec_t s, t, intensity;
346 #define NORMSIZE 64
347         unsigned char *data;
348         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
349         for (side = 0;side < 6;side++)
350         {
351                 for (y = 0;y < NORMSIZE;y++)
352                 {
353                         for (x = 0;x < NORMSIZE;x++)
354                         {
355                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
356                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
357                                 switch(side)
358                                 {
359                                 default:
360                                 case 0:
361                                         v[0] = 1;
362                                         v[1] = -t;
363                                         v[2] = -s;
364                                         break;
365                                 case 1:
366                                         v[0] = -1;
367                                         v[1] = -t;
368                                         v[2] = s;
369                                         break;
370                                 case 2:
371                                         v[0] = s;
372                                         v[1] = 1;
373                                         v[2] = t;
374                                         break;
375                                 case 3:
376                                         v[0] = s;
377                                         v[1] = -1;
378                                         v[2] = -t;
379                                         break;
380                                 case 4:
381                                         v[0] = s;
382                                         v[1] = -t;
383                                         v[2] = 1;
384                                         break;
385                                 case 5:
386                                         v[0] = -s;
387                                         v[1] = -t;
388                                         v[2] = -1;
389                                         break;
390                                 }
391                                 intensity = 127.0f / sqrt(DotProduct(v, v));
392                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
393                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
394                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
395                                 data[((side*64+y)*64+x)*4+3] = 255;
396                         }
397                 }
398         }
399         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
400         Mem_Free(data);
401 }
402
403 static void R_BuildFogTexture(void)
404 {
405         int x, b;
406 #define FOGWIDTH 256
407         unsigned char data1[FOGWIDTH][4];
408         //unsigned char data2[FOGWIDTH][4];
409         double d, r, alpha;
410
411         r_refdef.fogmasktable_start = r_refdef.fog_start;
412         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
413         r_refdef.fogmasktable_range = r_refdef.fogrange;
414         r_refdef.fogmasktable_density = r_refdef.fog_density;
415
416         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
417         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
418         {
419                 d = (x * r - r_refdef.fogmasktable_start);
420                 if(developer.integer >= 100)
421                         Con_Printf("%f ", d);
422                 d = max(0, d);
423                 if (r_fog_exp2.integer)
424                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
425                 else
426                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
427                 if(developer.integer >= 100)
428                         Con_Printf(" : %f ", alpha);
429                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
430                 if(developer.integer >= 100)
431                         Con_Printf(" = %f\n", alpha);
432                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
433         }
434
435         for (x = 0;x < FOGWIDTH;x++)
436         {
437                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
438                 data1[x][0] = b;
439                 data1[x][1] = b;
440                 data1[x][2] = b;
441                 data1[x][3] = 255;
442                 //data2[x][0] = 255 - b;
443                 //data2[x][1] = 255 - b;
444                 //data2[x][2] = 255 - b;
445                 //data2[x][3] = 255;
446         }
447         if (r_texture_fogattenuation)
448         {
449                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
450                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
451         }
452         else
453         {
454                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
455                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
456         }
457 }
458
459 static const char *builtinshaderstring =
460 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
461 "// written by Forest 'LordHavoc' Hale\n"
462 "\n"
463 "// enable various extensions depending on permutation:\n"
464 "\n"
465 "#ifdef VERTEX_SHADER\n"
466 "uniform mat4 ModelViewProjectionMatrix;\n"
467 "#endif\n"
468 "\n"
469 "#ifdef MODE_DEPTH_OR_SHADOW\n"
470 "#ifdef VERTEX_SHADER\n"
471 "void main(void)\n"
472 "{\n"
473 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
474 "}\n"
475 "#endif\n"
476 "#else // !MODE_DEPTH_ORSHADOW\n"
477 "#ifdef MODE_SHOWDEPTH\n"
478 "#ifdef VERTEX_SHADER\n"
479 "void main(void)\n"
480 "{\n"
481 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
482 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
483 "}\n"
484 "#endif\n"
485 "\n"
486 "#ifdef FRAGMENT_SHADER\n"
487 "void main(void)\n"
488 "{\n"
489 "       gl_FragColor = gl_Color;\n"
490 "}\n"
491 "#endif\n"
492 "#else // !MODE_SHOWDEPTH\n"
493 "#ifdef MODE_POSTPROCESS\n"
494 "varying vec2 TexCoord1;\n"
495 "varying vec2 TexCoord2;\n"
496 "\n"
497 "#ifdef VERTEX_SHADER\n"
498 "void main(void)\n"
499 "{\n"
500 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
501 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
502 "#ifdef USEBLOOM\n"
503 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
504 "#endif\n"
505 "}\n"
506 "#endif\n"
507 "\n"
508 "#ifdef FRAGMENT_SHADER\n"
509 "uniform sampler2D Texture_First;\n"
510 "#ifdef USEBLOOM\n"
511 "uniform sampler2D Texture_Second;\n"
512 "#endif\n"
513 "#ifdef USEGAMMARAMPS\n"
514 "uniform sampler2D Texture_GammaRamps;\n"
515 "#endif\n"
516 "#ifdef USESATURATION\n"
517 "uniform float Saturation;\n"
518 "#endif\n"
519 "#ifdef USEVIEWTINT\n"
520 "uniform vec4 ViewTintColor;\n"
521 "#endif\n"
522 "//uncomment these if you want to use them:\n"
523 "uniform vec4 UserVec1;\n"
524 "// uniform vec4 UserVec2;\n"
525 "// uniform vec4 UserVec3;\n"
526 "// uniform vec4 UserVec4;\n"
527 "// uniform float ClientTime;\n"
528 "uniform vec2 PixelSize;\n"
529 "void main(void)\n"
530 "{\n"
531 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
532 "#ifdef USEBLOOM\n"
533 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
534 "#endif\n"
535 "#ifdef USEVIEWTINT\n"
536 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
537 "#endif\n"
538 "\n"
539 "#ifdef USEPOSTPROCESSING\n"
540 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
541 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
542 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
543 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
544 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
545 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
546 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
547 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
548 "#endif\n"
549 "\n"
550 "#ifdef USESATURATION\n"
551 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
552 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
553 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
554 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
555 "#endif\n"
556 "\n"
557 "#ifdef USEGAMMARAMPS\n"
558 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
559 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
560 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
561 "#endif\n"
562 "}\n"
563 "#endif\n"
564 "#else // !MODE_POSTPROCESS\n"
565 "#ifdef MODE_GENERIC\n"
566 "#ifdef USEDIFFUSE\n"
567 "varying vec2 TexCoord1;\n"
568 "#endif\n"
569 "#ifdef USESPECULAR\n"
570 "varying vec2 TexCoord2;\n"
571 "#endif\n"
572 "#ifdef VERTEX_SHADER\n"
573 "void main(void)\n"
574 "{\n"
575 "       gl_FrontColor = gl_Color;\n"
576 "#ifdef USEDIFFUSE\n"
577 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
578 "#endif\n"
579 "#ifdef USESPECULAR\n"
580 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
581 "#endif\n"
582 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
583 "}\n"
584 "#endif\n"
585 "\n"
586 "#ifdef FRAGMENT_SHADER\n"
587 "#ifdef USEDIFFUSE\n"
588 "uniform sampler2D Texture_First;\n"
589 "#endif\n"
590 "#ifdef USESPECULAR\n"
591 "uniform sampler2D Texture_Second;\n"
592 "#endif\n"
593 "\n"
594 "void main(void)\n"
595 "{\n"
596 "       gl_FragColor = gl_Color;\n"
597 "#ifdef USEDIFFUSE\n"
598 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
599 "#endif\n"
600 "\n"
601 "#ifdef USESPECULAR\n"
602 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
603 "# ifdef USECOLORMAPPING\n"
604 "       gl_FragColor *= tex2;\n"
605 "# endif\n"
606 "# ifdef USEGLOW\n"
607 "       gl_FragColor += tex2;\n"
608 "# endif\n"
609 "# ifdef USEVERTEXTEXTUREBLEND\n"
610 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
611 "# endif\n"
612 "#endif\n"
613 "}\n"
614 "#endif\n"
615 "#else // !MODE_GENERIC\n"
616 "#ifdef MODE_BLOOMBLUR\n"
617 "varying TexCoord;\n"
618 "#ifdef VERTEX_SHADER\n"
619 "void main(void)\n"
620 "{\n"
621 "       gl_FrontColor = gl_Color;\n"
622 "       TexCoord = gl_MultiTexCoord0.xy;\n"
623 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
624 "}\n"
625 "#endif\n"
626 "\n"
627 "#ifdef FRAGMENT_SHADER\n"
628 "uniform sampler2D Texture_First;\n"
629 "uniform vec4 BloomBlur_Parameters;\n"
630 "\n"
631 "void main(void)\n"
632 "{\n"
633 "       int i;\n"
634 "       vec2 tc = TexCoord;\n"
635 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
636 "       tc += BloomBlur_Parameters.xy;\n"
637 "       for (i = 1;i < SAMPLES;i++)\n"
638 "       {\n"
639 "               color += texture2D(Texture_First, tc).rgb;\n"
640 "               tc += BloomBlur_Parameters.xy;\n"
641 "       }\n"
642 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
643 "}\n"
644 "#endif\n"
645 "#else // !MODE_BLOOMBLUR\n"
646 "#ifdef MODE_REFRACTION\n"
647 "varying vec2 TexCoord;\n"
648 "varying vec4 ModelViewProjectionPosition;\n"
649 "uniform mat4 TexMatrix;\n"
650 "#ifdef VERTEX_SHADER\n"
651 "\n"
652 "void main(void)\n"
653 "{\n"
654 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
655 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
656 "       ModelViewProjectionPosition = gl_Position;\n"
657 "}\n"
658 "#endif\n"
659 "\n"
660 "#ifdef FRAGMENT_SHADER\n"
661 "uniform sampler2D Texture_Normal;\n"
662 "uniform sampler2D Texture_Refraction;\n"
663 "uniform sampler2D Texture_Reflection;\n"
664 "\n"
665 "uniform vec4 DistortScaleRefractReflect;\n"
666 "uniform vec4 ScreenScaleRefractReflect;\n"
667 "uniform vec4 ScreenCenterRefractReflect;\n"
668 "uniform vec4 RefractColor;\n"
669 "uniform vec4 ReflectColor;\n"
670 "uniform float ReflectFactor;\n"
671 "uniform float ReflectOffset;\n"
672 "\n"
673 "void main(void)\n"
674 "{\n"
675 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
676 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
677 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
678 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
679 "       // FIXME temporary hack to detect the case that the reflection\n"
680 "       // gets blackened at edges due to leaving the area that contains actual\n"
681 "       // content.\n"
682 "       // Remove this 'ack once we have a better way to stop this thing from\n"
683 "       // 'appening.\n"
684 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
685 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
686 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
687 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
688 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
689 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
690 "}\n"
691 "#endif\n"
692 "#else // !MODE_REFRACTION\n"
693 "#ifdef MODE_WATER\n"
694 "varying vec2 TexCoord;\n"
695 "varying vec3 EyeVector;\n"
696 "varying vec4 ModelViewProjectionPosition;\n"
697 "#ifdef VERTEX_SHADER\n"
698 "uniform vec3 EyePosition;\n"
699 "uniform mat4 TexMatrix;\n"
700 "\n"
701 "void main(void)\n"
702 "{\n"
703 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
704 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
705 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
706 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
707 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
708 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
709 "       ModelViewProjectionPosition = gl_Position;\n"
710 "}\n"
711 "#endif\n"
712 "\n"
713 "#ifdef FRAGMENT_SHADER\n"
714 "uniform sampler2D Texture_Normal;\n"
715 "uniform sampler2D Texture_Refraction;\n"
716 "uniform sampler2D Texture_Reflection;\n"
717 "\n"
718 "uniform vec4 DistortScaleRefractReflect;\n"
719 "uniform vec4 ScreenScaleRefractReflect;\n"
720 "uniform vec4 ScreenCenterRefractReflect;\n"
721 "uniform vec4 RefractColor;\n"
722 "uniform vec4 ReflectColor;\n"
723 "uniform float ReflectFactor;\n"
724 "uniform float ReflectOffset;\n"
725 "\n"
726 "void main(void)\n"
727 "{\n"
728 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
729 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
730 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
731 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
732 "       // FIXME temporary hack to detect the case that the reflection\n"
733 "       // gets blackened at edges due to leaving the area that contains actual\n"
734 "       // content.\n"
735 "       // Remove this 'ack once we have a better way to stop this thing from\n"
736 "       // 'appening.\n"
737 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
738 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
739 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
740 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
741 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
742 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
743 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
744 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
745 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
746 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
747 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
748 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
749 "}\n"
750 "#endif\n"
751 "#else // !MODE_WATER\n"
752 "\n"
753 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
754 "# extension GL_ARB_texture_rectangle : enable\n"
755 "#endif\n"
756 "\n"
757 "#ifdef USESHADOWMAP2D\n"
758 "# ifdef GL_EXT_gpu_shader4\n"
759 "#   extension GL_EXT_gpu_shader4 : enable\n"
760 "# endif\n"
761 "# ifdef GL_ARB_texture_gather\n"
762 "#   extension GL_ARB_texture_gather : enable\n"
763 "# else\n"
764 "#   ifdef GL_AMD_texture_texture4\n"
765 "#     extension GL_AMD_texture_texture4 : enable\n"
766 "#   endif\n"
767 "# endif\n"
768 "#endif\n"
769 "\n"
770 "#ifdef USESHADOWMAPCUBE\n"
771 "# extension GL_EXT_gpu_shader4 : enable\n"
772 "#endif\n"
773 "\n"
774 "#ifdef USESHADOWSAMPLER\n"
775 "# extension GL_ARB_shadow : enable\n"
776 "#endif\n"
777 "\n"
778 "// common definitions between vertex shader and fragment shader:\n"
779 "\n"
780 "//#ifdef __GLSL_CG_DATA_TYPES\n"
781 "//# define myhalf half\n"
782 "//# define myhalf2 half2\n"
783 "//# define myhalf3half3\n"
784 "//# define myhalf4 half4\n"
785 "//#else\n"
786 "# define myhalf float\n"
787 "# define myhalf2 vec2\n"
788 "# define myhalf3 vec3\n"
789 "# define myhalf4 vec4\n"
790 "//#endif\n"
791 "\n"
792 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
793 "# define USEFOG\n"
794 "#endif\n"
795 "\n"
796 "varying vec2 TexCoord;\n"
797 "#ifdef USEVERTEXTEXTUREBLEND\n"
798 "varying vec2 TexCoord2;\n"
799 "#endif\n"
800 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
801 "#define USELIGHTMAP\n"
802 "varying vec2 TexCoordLightmap;\n"
803 "#endif\n"
804 "\n"
805 "#ifdef MODE_LIGHTSOURCE\n"
806 "varying vec3 CubeVector;\n"
807 "#endif\n"
808 "\n"
809 "#ifdef MODE_LIGHTSOURCE\n"
810 "varying vec3 LightVector;\n"
811 "#endif\n"
812 "#if defined(MODE_LIGHTDIRECTION)\n"
813 "varying vec3 LightVector;\n"
814 "#endif\n"
815 "\n"
816 "#if defined(USEOFFSETMAPPING) || defined(USESPECULAR)\n"
817 "//#if defined(USEOFFSETMAPPING) || defined(USESPECULAR) || defined(MODE_LIGHTDIRECTION) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
818 "#define USEEYEVECTOR\n"
819 "varying vec3 EyeVector;\n"
820 "#endif\n"
821 "#ifdef USEFOG\n"
822 "varying vec3 EyeVectorModelSpace;\n"
823 "varying float FogPlaneVertexDist;\n"
824 "#endif\n"
825 "\n"
826 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
827 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
828 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
829 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
830 "#endif\n"
831 "\n"
832 "#ifdef USEREFLECTION\n"
833 "varying vec4 ModelViewProjectionPosition;\n"
834 "#endif\n"
835 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
836 "uniform vec3 LightPosition;\n"
837 "varying vec4 ModelViewPosition;\n"
838 "#endif\n"
839 "\n"
840 "#ifdef MODE_LIGHTSOURCE\n"
841 "uniform vec3 LightPosition;\n"
842 "#endif\n"
843 "uniform vec3 EyePosition;\n"
844 "#ifdef MODE_LIGHTDIRECTION\n"
845 "uniform vec3 LightDir;\n"
846 "#endif\n"
847 "uniform vec4 FogPlane;\n"
848 "\n"
849 "\n"
850 "\n"
851 "\n"
852 "\n"
853 "// vertex shader specific:\n"
854 "#ifdef VERTEX_SHADER\n"
855 "\n"
856 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
857 "\n"
858 "#ifdef MODE_DEFERREDGEOMETRY\n"
859 "uniform mat4 TexMatrix;\n"
860 "#ifdef USEVERTEXTEXTUREBLEND\n"
861 "uniform mat4 BackgroundTexMatrix;\n"
862 "#endif\n"
863 "uniform mat4 ModelViewMatrix;\n"
864 "void main(void)\n"
865 "{\n"
866 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
867 "#ifdef USEVERTEXTEXTUREBLEND\n"
868 "       gl_FrontColor = gl_Color;\n"
869 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
870 "#endif\n"
871 "\n"
872 "       // transform unnormalized eye direction into tangent space\n"
873 "#ifdef USEOFFSETMAPPING\n"
874 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
875 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
876 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
877 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
878 "#endif\n"
879 "\n"
880 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
881 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
882 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
883 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
884 "}\n"
885 "#else // !MODE_DEFERREDGEOMETRY\n"
886 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
887 "uniform mat4 ModelViewMatrix;\n"
888 "void main(void)\n"
889 "{\n"
890 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
891 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
892 "}\n"
893 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
894 "uniform mat4 TexMatrix;\n"
895 "#ifdef USEVERTEXTEXTUREBLEND\n"
896 "uniform mat4 BackgroundTexMatrix;\n"
897 "#endif\n"
898 "#ifdef MODE_LIGHTSOURCE\n"
899 "uniform mat4 ModelToLight;\n"
900 "#endif\n"
901 "void main(void)\n"
902 "{\n"
903 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
904 "       gl_FrontColor = gl_Color;\n"
905 "#endif\n"
906 "       // copy the surface texcoord\n"
907 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
908 "#ifdef USEVERTEXTEXTUREBLEND\n"
909 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
910 "#endif\n"
911 "#ifdef USELIGHTMAP\n"
912 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
913 "#endif\n"
914 "\n"
915 "#ifdef MODE_LIGHTSOURCE\n"
916 "       // transform vertex position into light attenuation/cubemap space\n"
917 "       // (-1 to +1 across the light box)\n"
918 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
919 "\n"
920 "# ifdef USEDIFFUSE\n"
921 "       // transform unnormalized light direction into tangent space\n"
922 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
923 "       //  normalize it per pixel)\n"
924 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
925 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
926 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
927 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
928 "# endif\n"
929 "#endif\n"
930 "\n"
931 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
932 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
933 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
934 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
935 "#endif\n"
936 "\n"
937 "       // transform unnormalized eye direction into tangent space\n"
938 "#ifdef USEEYEVECTOR\n"
939 "#ifndef USEFOG\n"
940 "       vec3 EyeVectorModelSpace;\n"
941 "#endif\n"
942 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
943 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
944 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
945 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
946 "#endif\n"
947 "\n"
948 "#ifdef USEFOG\n"
949 "#ifndef USEEYEVECTOR\n"
950 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
951 "#endif\n"
952 "       FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
953 "#endif\n"
954 "\n"
955 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
956 "       VectorS = gl_MultiTexCoord1.xyz;\n"
957 "       VectorT = gl_MultiTexCoord2.xyz;\n"
958 "       VectorR = gl_MultiTexCoord3.xyz;\n"
959 "#endif\n"
960 "\n"
961 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
962 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
963 "\n"
964 "#ifdef USEREFLECTION\n"
965 "       ModelViewProjectionPosition = gl_Position;\n"
966 "#endif\n"
967 "}\n"
968 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
969 "#endif // !MODE_DEFERREDGEOMETRY\n"
970 "\n"
971 "#endif // VERTEX_SHADER\n"
972 "\n"
973 "\n"
974 "\n"
975 "\n"
976 "// fragment shader specific:\n"
977 "#ifdef FRAGMENT_SHADER\n"
978 "\n"
979 "uniform sampler2D Texture_Normal;\n"
980 "uniform sampler2D Texture_Color;\n"
981 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
982 "uniform sampler2D Texture_Gloss;\n"
983 "//#endif\n"
984 "#ifdef USEGLOW\n"
985 "uniform sampler2D Texture_Glow;\n"
986 "#endif\n"
987 "#ifdef USEVERTEXTEXTUREBLEND\n"
988 "uniform sampler2D Texture_SecondaryNormal;\n"
989 "uniform sampler2D Texture_SecondaryColor;\n"
990 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
991 "uniform sampler2D Texture_SecondaryGloss;\n"
992 "//#endif\n"
993 "#ifdef USEGLOW\n"
994 "uniform sampler2D Texture_SecondaryGlow;\n"
995 "#endif\n"
996 "#endif\n"
997 "#ifdef USECOLORMAPPING\n"
998 "uniform sampler2D Texture_Pants;\n"
999 "uniform sampler2D Texture_Shirt;\n"
1000 "#endif\n"
1001 "#ifdef USEFOG\n"
1002 "uniform sampler2D Texture_FogMask;\n"
1003 "#endif\n"
1004 "#ifdef USELIGHTMAP\n"
1005 "uniform sampler2D Texture_Lightmap;\n"
1006 "#endif\n"
1007 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1008 "uniform sampler2D Texture_Deluxemap;\n"
1009 "#endif\n"
1010 "#ifdef USEREFLECTION\n"
1011 "uniform sampler2D Texture_Reflection;\n"
1012 "#endif\n"
1013 "\n"
1014 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1015 "uniform sampler2DRect Texture_ScreenDepth;\n"
1016 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
1017 "#endif\n"
1018 "#ifdef USEDEFERREDLIGHTMAP\n"
1019 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
1020 "uniform sampler2DRect Texture_ScreenSpecular;\n"
1021 "#endif\n"
1022 "\n"
1023 "uniform myhalf3 Color_Pants;\n"
1024 "uniform myhalf3 Color_Shirt;\n"
1025 "uniform myhalf3 FogColor;\n"
1026 "\n"
1027 "#ifdef USEFOG\n"
1028 "uniform float FogRangeRecip;\n"
1029 "uniform float FogPlaneViewDist;\n"
1030 "uniform float FogHeightFade;\n"
1031 "myhalf FogVertex(void)\n"
1032 "{\n"
1033 "       float fogfrac;\n"
1034 "#ifdef USEFOGOUTSIDE\n"
1035 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1036 "#else\n"
1037 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1038 "#endif\n"
1039 "       return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1040 "}\n"
1041 "#endif\n"
1042 "\n"
1043 "#ifdef USEOFFSETMAPPING\n"
1044 "uniform float OffsetMapping_Scale;\n"
1045 "vec2 OffsetMapping(vec2 TexCoord)\n"
1046 "{\n"
1047 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1048 "       // 14 sample relief mapping: linear search and then binary search\n"
1049 "       // this basically steps forward a small amount repeatedly until it finds\n"
1050 "       // itself inside solid, then jitters forward and back using decreasing\n"
1051 "       // amounts to find the impact\n"
1052 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1053 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1054 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1055 "       vec3 RT = vec3(TexCoord, 1);\n"
1056 "       OffsetVector *= 0.1;\n"
1057 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1058 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1059 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1060 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1061 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1062 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1063 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1064 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1065 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1066 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1067 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1068 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1069 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1070 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1071 "       return RT.xy;\n"
1072 "#else\n"
1073 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1074 "       // this basically moves forward the full distance, and then backs up based\n"
1075 "       // on height of samples\n"
1076 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1077 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1078 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1079 "       TexCoord += OffsetVector;\n"
1080 "       OffsetVector *= 0.333;\n"
1081 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1082 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1083 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1084 "       return TexCoord;\n"
1085 "#endif\n"
1086 "}\n"
1087 "#endif // USEOFFSETMAPPING\n"
1088 "\n"
1089 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1090 "uniform sampler2D Texture_Attenuation;\n"
1091 "uniform samplerCube Texture_Cube;\n"
1092 "\n"
1093 "#ifdef USESHADOWMAPRECT\n"
1094 "# ifdef USESHADOWSAMPLER\n"
1095 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1096 "# else\n"
1097 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1098 "# endif\n"
1099 "#endif\n"
1100 "\n"
1101 "#ifdef USESHADOWMAP2D\n"
1102 "# ifdef USESHADOWSAMPLER\n"
1103 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1104 "# else\n"
1105 "uniform sampler2D Texture_ShadowMap2D;\n"
1106 "# endif\n"
1107 "#endif\n"
1108 "\n"
1109 "#ifdef USESHADOWMAPVSDCT\n"
1110 "uniform samplerCube Texture_CubeProjection;\n"
1111 "#endif\n"
1112 "\n"
1113 "#ifdef USESHADOWMAPCUBE\n"
1114 "# ifdef USESHADOWSAMPLER\n"
1115 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1116 "# else\n"
1117 "uniform samplerCube Texture_ShadowMapCube;\n"
1118 "# endif\n"
1119 "#endif\n"
1120 "\n"
1121 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1122 "uniform vec2 ShadowMap_TextureScale;\n"
1123 "uniform vec4 ShadowMap_Parameters;\n"
1124 "#endif\n"
1125 "\n"
1126 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1127 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1128 "{\n"
1129 "       vec3 adir = abs(dir);\n"
1130 "# ifndef USESHADOWMAPVSDCT\n"
1131 "       vec2 tc;\n"
1132 "       vec2 offset;\n"
1133 "       float ma;\n"
1134 "       if (adir.x > adir.y)\n"
1135 "       {\n"
1136 "               if (adir.x > adir.z) // X\n"
1137 "               {\n"
1138 "                       ma = adir.x;\n"
1139 "                       tc = dir.zy;\n"
1140 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1141 "               }\n"
1142 "               else // Z\n"
1143 "               {\n"
1144 "                       ma = adir.z;\n"
1145 "                       tc = dir.xy;\n"
1146 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1147 "               }\n"
1148 "       }\n"
1149 "       else\n"
1150 "       {\n"
1151 "               if (adir.y > adir.z) // Y\n"
1152 "               {\n"
1153 "                       ma = adir.y;\n"
1154 "                       tc = dir.xz;\n"
1155 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1156 "               }\n"
1157 "               else // Z\n"
1158 "               {\n"
1159 "                       ma = adir.z;\n"
1160 "                       tc = dir.xy;\n"
1161 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1162 "               }\n"
1163 "       }\n"
1164 "\n"
1165 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1166 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1167 "       stc.z += ShadowMap_Parameters.z;\n"
1168 "       return stc;\n"
1169 "# else\n"
1170 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1171 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1172 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1173 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1174 "       stc.z += ShadowMap_Parameters.z;\n"
1175 "       return stc;\n"
1176 "# endif\n"
1177 "}\n"
1178 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1179 "\n"
1180 "#ifdef USESHADOWMAPCUBE\n"
1181 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1182 "{\n"
1183 "    vec3 adir = abs(dir);\n"
1184 "    return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1185 "}\n"
1186 "#endif\n"
1187 "\n"
1188 "# ifdef USESHADOWMAPRECT\n"
1189 "float ShadowMapCompare(vec3 dir)\n"
1190 "{\n"
1191 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1192 "       float f;\n"
1193 "#  ifdef USESHADOWSAMPLER\n"
1194 "\n"
1195 "#    ifdef USESHADOWMAPPCF\n"
1196 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1197 "    f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1198 "#    else\n"
1199 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1200 "#    endif\n"
1201 "\n"
1202 "#  else\n"
1203 "\n"
1204 "#    ifdef USESHADOWMAPPCF\n"
1205 "#      if USESHADOWMAPPCF > 1\n"
1206 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1207 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1208 "    vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1209 "    vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1210 "    vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1211 "    vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1212 "    vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1213 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1214 "#      else\n"
1215 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1216 "    vec2 offset = fract(shadowmaptc.xy);\n"
1217 "    vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1218 "    vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1219 "    vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1220 "    vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1221 "    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1222 "#      endif\n"
1223 "#    else\n"
1224 "    f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1225 "#    endif\n"
1226 "\n"
1227 "#  endif\n"
1228 "       return f;\n"
1229 "}\n"
1230 "# endif\n"
1231 "\n"
1232 "# ifdef USESHADOWMAP2D\n"
1233 "float ShadowMapCompare(vec3 dir)\n"
1234 "{\n"
1235 "    vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1236 "    float f;\n"
1237 "\n"
1238 "#  ifdef USESHADOWSAMPLER\n"
1239 "#    ifdef USESHADOWMAPPCF\n"
1240 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1241 "    vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1242 "    f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1243 "#    else\n"
1244 "    f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1245 "#    endif\n"
1246 "#  else\n"
1247 "#    ifdef USESHADOWMAPPCF\n"
1248 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1249 "#      ifdef GL_ARB_texture_gather\n"
1250 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1251 "#      else\n"
1252 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1253 "#      endif\n"
1254 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1255 "    center *= ShadowMap_TextureScale;\n"
1256 "    vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1257 "    vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1258 "    vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1259 "    vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1260 "    vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1261 "                mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1262 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1263 "#     else\n"
1264 "#      ifdef GL_EXT_gpu_shader4\n"
1265 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1266 "#      else\n"
1267 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1268 "#      endif\n"
1269 "#      if USESHADOWMAPPCF > 1\n"
1270 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1271 "    center *= ShadowMap_TextureScale;\n"
1272 "    vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1273 "    vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1274 "    vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1275 "    vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1276 "    vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1277 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1278 "#      else\n"
1279 "    vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1280 "    vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1281 "    vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1282 "    vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1283 "    vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1284 "    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1285 "#      endif\n"
1286 "#     endif\n"
1287 "#    else\n"
1288 "    f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1289 "#    endif\n"
1290 "#  endif\n"
1291 "    return f;\n"
1292 "}\n"
1293 "# endif\n"
1294 "\n"
1295 "# ifdef USESHADOWMAPCUBE\n"
1296 "float ShadowMapCompare(vec3 dir)\n"
1297 "{\n"
1298 "    // apply depth texture cubemap as light filter\n"
1299 "    vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1300 "    float f;\n"
1301 "#  ifdef USESHADOWSAMPLER\n"
1302 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1303 "#  else\n"
1304 "    f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1305 "#  endif\n"
1306 "    return f;\n"
1307 "}\n"
1308 "# endif\n"
1309 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1310 "\n"
1311 "#ifdef MODE_DEFERREDGEOMETRY\n"
1312 "void main(void)\n"
1313 "{\n"
1314 "#ifdef USEOFFSETMAPPING\n"
1315 "       // apply offsetmapping\n"
1316 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1317 "#define TexCoord TexCoordOffset\n"
1318 "#endif\n"
1319 "\n"
1320 "#ifdef USEALPHAKILL\n"
1321 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1322 "               discard;\n"
1323 "#endif\n"
1324 "\n"
1325 "#ifdef USEVERTEXTEXTUREBLEND\n"
1326 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1327 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1328 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1329 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1330 "#endif\n"
1331 "\n"
1332 "#ifdef USEVERTEXTEXTUREBLEND\n"
1333 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1334 "#else\n"
1335 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1336 "#endif\n"
1337 "\n"
1338 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1339 "}\n"
1340 "#else // !MODE_DEFERREDGEOMETRY\n"
1341 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1342 "uniform mat4 ViewToLight;\n"
1343 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1344 "uniform vec2 ScreenToDepth;\n"
1345 "uniform myhalf3 DeferredColor_Ambient;\n"
1346 "uniform myhalf3 DeferredColor_Diffuse;\n"
1347 "#ifdef USESPECULAR\n"
1348 "uniform myhalf3 DeferredColor_Specular;\n"
1349 "uniform myhalf SpecularPower;\n"
1350 "#endif\n"
1351 "void main(void)\n"
1352 "{\n"
1353 "       // calculate viewspace pixel position\n"
1354 "       vec3 position;\n"
1355 "       position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1356 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1357 "       // decode viewspace pixel normal\n"
1358 "       myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1359 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1360 "       // surfacenormal = pixel normal in viewspace\n"
1361 "       // LightVector = pixel to light in viewspace\n"
1362 "       // CubeVector = position in lightspace\n"
1363 "       // eyevector = pixel to view in viewspace\n"
1364 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1365 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1366 "#ifdef USEDIFFUSE\n"
1367 "       // calculate diffuse shading\n"
1368 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1369 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1370 "#endif\n"
1371 "#ifdef USESPECULAR\n"
1372 "       // calculate directional shading\n"
1373 "       vec3 eyevector = position * -1.0;\n"
1374 "#  ifdef USEEXACTSPECULARMATH\n"
1375 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1376 "#  else\n"
1377 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1378 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1379 "#  endif\n"
1380 "#endif\n"
1381 "\n"
1382 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1383 "       fade *= ShadowMapCompare(CubeVector);\n"
1384 "#endif\n"
1385 "\n"
1386 "#ifdef USEDIFFUSE\n"
1387 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1388 "#else\n"
1389 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1390 "#endif\n"
1391 "#ifdef USESPECULAR\n"
1392 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1393 "#else\n"
1394 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1395 "#endif\n"
1396 "\n"
1397 "# ifdef USECUBEFILTER\n"
1398 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1399 "       gl_FragData[0] *= cubecolor;\n"
1400 "       gl_FragData[1] *= cubecolor;\n"
1401 "# endif\n"
1402 "}\n"
1403 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1404 "#ifdef USEDEFERREDLIGHTMAP\n"
1405 "uniform myhalf3 DeferredMod_Diffuse;\n"
1406 "uniform myhalf3 DeferredMod_Specular;\n"
1407 "#endif\n"
1408 "uniform myhalf3 Color_Ambient;\n"
1409 "uniform myhalf3 Color_Diffuse;\n"
1410 "uniform myhalf3 Color_Specular;\n"
1411 "uniform myhalf SpecularPower;\n"
1412 "#ifdef USEGLOW\n"
1413 "uniform myhalf3 Color_Glow;\n"
1414 "#endif\n"
1415 "uniform myhalf Alpha;\n"
1416 "#ifdef USEREFLECTION\n"
1417 "uniform vec4 DistortScaleRefractReflect;\n"
1418 "uniform vec4 ScreenScaleRefractReflect;\n"
1419 "uniform vec4 ScreenCenterRefractReflect;\n"
1420 "uniform myhalf4 ReflectColor;\n"
1421 "#endif\n"
1422 "#ifdef MODE_LIGHTDIRECTION\n"
1423 "uniform myhalf3 LightColor;\n"
1424 "#endif\n"
1425 "#ifdef MODE_LIGHTSOURCE\n"
1426 "uniform myhalf3 LightColor;\n"
1427 "#endif\n"
1428 "void main(void)\n"
1429 "{\n"
1430 "#ifdef USEOFFSETMAPPING\n"
1431 "       // apply offsetmapping\n"
1432 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1433 "#define TexCoord TexCoordOffset\n"
1434 "#endif\n"
1435 "\n"
1436 "       // combine the diffuse textures (base, pants, shirt)\n"
1437 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1438 "#ifdef USEALPHAKILL\n"
1439 "       if (color.a < 0.5)\n"
1440 "               discard;\n"
1441 "#endif\n"
1442 "       color.a *= Alpha;\n"
1443 "#ifdef USECOLORMAPPING\n"
1444 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1445 "#endif\n"
1446 "#ifdef USEVERTEXTEXTUREBLEND\n"
1447 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1448 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1449 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1450 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1451 "       color.a = 1.0;\n"
1452 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1453 "#endif\n"
1454 "\n"
1455 "       // get the surface normal\n"
1456 "#ifdef USEVERTEXTEXTUREBLEND\n"
1457 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1458 "#else\n"
1459 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1460 "#endif\n"
1461 "\n"
1462 "       // get the material colors\n"
1463 "       myhalf3 diffusetex = color.rgb;\n"
1464 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1465 "# ifdef USEVERTEXTEXTUREBLEND\n"
1466 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1467 "# else\n"
1468 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1469 "# endif\n"
1470 "#endif\n"
1471 "\n"
1472 "\n"
1473 "\n"
1474 "\n"
1475 "#ifdef MODE_LIGHTSOURCE\n"
1476 "       // light source\n"
1477 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1478 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1479 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1480 "#ifdef USESPECULAR\n"
1481 "#ifdef USEEXACTSPECULARMATH\n"
1482 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1483 "#else\n"
1484 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1485 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1486 "#endif\n"
1487 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1488 "#endif\n"
1489 "       color.rgb *= LightColor;\n"
1490 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1491 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1492 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1493 "#endif\n"
1494 "# ifdef USECUBEFILTER\n"
1495 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1496 "# endif\n"
1497 "#endif // MODE_LIGHTSOURCE\n"
1498 "\n"
1499 "\n"
1500 "\n"
1501 "\n"
1502 "#ifdef MODE_LIGHTDIRECTION\n"
1503 "#define SHADING\n"
1504 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1505 "#define lightcolor LightColor\n"
1506 "#endif // MODE_LIGHTDIRECTION\n"
1507 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1508 "#define SHADING\n"
1509 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1510 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1511 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1512 "       // convert modelspace light vector to tangentspace\n"
1513 "       myhalf3 lightnormal;\n"
1514 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1515 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1516 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1517 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1518 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1519 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1520 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1521 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1522 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1523 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1524 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1525 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1526 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1527 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1528 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1529 "#define SHADING\n"
1530 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1531 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1532 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1533 "#endif\n"
1534 "\n"
1535 "\n"
1536 "\n"
1537 "\n"
1538 "#ifdef MODE_LIGHTMAP\n"
1539 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1540 "#endif // MODE_LIGHTMAP\n"
1541 "#ifdef MODE_VERTEXCOLOR\n"
1542 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1543 "#endif // MODE_VERTEXCOLOR\n"
1544 "#ifdef MODE_FLATCOLOR\n"
1545 "       color.rgb = diffusetex * Color_Ambient;\n"
1546 "#endif // MODE_FLATCOLOR\n"
1547 "\n"
1548 "\n"
1549 "\n"
1550 "\n"
1551 "#ifdef SHADING\n"
1552 "# ifdef USEDIFFUSE\n"
1553 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1554 "#  ifdef USESPECULAR\n"
1555 "#   ifdef USEEXACTSPECULARMATH\n"
1556 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1557 "#   else\n"
1558 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1559 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1560 "#   endif\n"
1561 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1562 "#  else\n"
1563 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1564 "#  endif\n"
1565 "# else\n"
1566 "       color.rgb = diffusetex * Color_Ambient;\n"
1567 "# endif\n"
1568 "#endif\n"
1569 "\n"
1570 "#ifdef USEDEFERREDLIGHTMAP\n"
1571 "       color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1572 "       color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1573 "#endif\n"
1574 "\n"
1575 "#ifdef USEGLOW\n"
1576 "#ifdef USEVERTEXTEXTUREBLEND\n"
1577 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1578 "#else\n"
1579 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1580 "#endif\n"
1581 "#endif\n"
1582 "\n"
1583 "#ifdef USEFOG\n"
1584 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1585 "#endif\n"
1586 "\n"
1587 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1588 "#ifdef USEREFLECTION\n"
1589 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1590 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1591 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1592 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1593 "       // FIXME temporary hack to detect the case that the reflection\n"
1594 "       // gets blackened at edges due to leaving the area that contains actual\n"
1595 "       // content.\n"
1596 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1597 "       // 'appening.\n"
1598 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1599 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1600 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1601 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1602 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1603 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1604 "#endif\n"
1605 "\n"
1606 "       gl_FragColor = vec4(color);\n"
1607 "}\n"
1608 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1609 "#endif // !MODE_DEFERREDGEOMETRY\n"
1610 "\n"
1611 "#endif // FRAGMENT_SHADER\n"
1612 "\n"
1613 "#endif // !MODE_WATER\n"
1614 "#endif // !MODE_REFRACTION\n"
1615 "#endif // !MODE_BLOOMBLUR\n"
1616 "#endif // !MODE_GENERIC\n"
1617 "#endif // !MODE_POSTPROCESS\n"
1618 "#endif // !MODE_SHOWDEPTH\n"
1619 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1620 ;
1621
1622 const char *builtincgshaderstring = "";
1623
1624 typedef struct shaderpermutationinfo_s
1625 {
1626         const char *pretext;
1627         const char *name;
1628 }
1629 shaderpermutationinfo_t;
1630
1631 typedef struct shadermodeinfo_s
1632 {
1633         const char *vertexfilename;
1634         const char *geometryfilename;
1635         const char *fragmentfilename;
1636         const char *pretext;
1637         const char *name;
1638 }
1639 shadermodeinfo_t;
1640
1641 typedef enum shaderpermutation_e
1642 {
1643         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1644         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1645         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1646         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1647         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1648         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1649         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1650         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1651         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1652         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1653         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1654         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1655         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1656         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1657         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1658         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1659         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1660         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1661         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1662         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1663         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1664         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1665         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1666         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1667         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1668         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
1669         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
1670         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
1671 }
1672 shaderpermutation_t;
1673
1674 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1675 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1676 {
1677         {"#define USEDIFFUSE\n", " diffuse"},
1678         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1679         {"#define USEVIEWTINT\n", " viewtint"},
1680         {"#define USECOLORMAPPING\n", " colormapping"},
1681         {"#define USESATURATION\n", " saturation"},
1682         {"#define USEFOGINSIDE\n", " foginside"},
1683         {"#define USEFOGOUTSIDE\n", " fogoutside"},
1684         {"#define USEGAMMARAMPS\n", " gammaramps"},
1685         {"#define USECUBEFILTER\n", " cubefilter"},
1686         {"#define USEGLOW\n", " glow"},
1687         {"#define USEBLOOM\n", " bloom"},
1688         {"#define USESPECULAR\n", " specular"},
1689         {"#define USEPOSTPROCESSING\n", " postprocessing"},
1690         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1691         {"#define USEREFLECTION\n", " reflection"},
1692         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1693         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1694         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1695         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1696         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1697         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1698         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1699         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1700         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1701         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1702         {"#define USEALPHAKILL\n", " alphakill"},
1703 };
1704
1705 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1706 typedef enum shadermode_e
1707 {
1708         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1709         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1710         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1711         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1712         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1713         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1714         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1715         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1716         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1717         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1718         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1719         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1720         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1721         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1722         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1723         SHADERMODE_COUNT
1724 }
1725 shadermode_t;
1726
1727 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1728 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
1729 {
1730         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1731         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1732         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1733         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1734         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1735         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1736         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1737         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1738         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1739         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1740         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1741         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1742         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1743         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1744         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1745 };
1746
1747 #ifdef SUPPORTCG
1748 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
1749 {
1750         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
1751         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
1752         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1753         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
1754         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1755         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
1756         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1757         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1758         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1759         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1760         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
1761         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
1762         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
1763         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1764         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1765 };
1766 #endif
1767
1768 struct r_glsl_permutation_s;
1769 typedef struct r_glsl_permutation_s
1770 {
1771         /// hash lookup data
1772         struct r_glsl_permutation_s *hashnext;
1773         unsigned int mode;
1774         unsigned int permutation;
1775
1776         /// indicates if we have tried compiling this permutation already
1777         qboolean compiled;
1778         /// 0 if compilation failed
1779         int program;
1780         /// locations of detected uniforms in program object, or -1 if not found
1781         int loc_Texture_First;
1782         int loc_Texture_Second;
1783         int loc_Texture_GammaRamps;
1784         int loc_Texture_Normal;
1785         int loc_Texture_Color;
1786         int loc_Texture_Gloss;
1787         int loc_Texture_Glow;
1788         int loc_Texture_SecondaryNormal;
1789         int loc_Texture_SecondaryColor;
1790         int loc_Texture_SecondaryGloss;
1791         int loc_Texture_SecondaryGlow;
1792         int loc_Texture_Pants;
1793         int loc_Texture_Shirt;
1794         int loc_Texture_FogMask;
1795         int loc_Texture_Lightmap;
1796         int loc_Texture_Deluxemap;
1797         int loc_Texture_Attenuation;
1798         int loc_Texture_Cube;
1799         int loc_Texture_Refraction;
1800         int loc_Texture_Reflection;
1801         int loc_Texture_ShadowMapRect;
1802         int loc_Texture_ShadowMapCube;
1803         int loc_Texture_ShadowMap2D;
1804         int loc_Texture_CubeProjection;
1805         int loc_Texture_ScreenDepth;
1806         int loc_Texture_ScreenNormalMap;
1807         int loc_Texture_ScreenDiffuse;
1808         int loc_Texture_ScreenSpecular;
1809         int loc_Alpha;
1810         int loc_BloomBlur_Parameters;
1811         int loc_ClientTime;
1812         int loc_Color_Ambient;
1813         int loc_Color_Diffuse;
1814         int loc_Color_Specular;
1815         int loc_Color_Glow;
1816         int loc_Color_Pants;
1817         int loc_Color_Shirt;
1818         int loc_DeferredColor_Ambient;
1819         int loc_DeferredColor_Diffuse;
1820         int loc_DeferredColor_Specular;
1821         int loc_DeferredMod_Diffuse;
1822         int loc_DeferredMod_Specular;
1823         int loc_DistortScaleRefractReflect;
1824         int loc_EyePosition;
1825         int loc_FogColor;
1826         int loc_FogHeightFade;
1827         int loc_FogPlane;
1828         int loc_FogPlaneViewDist;
1829         int loc_FogRangeRecip;
1830         int loc_LightColor;
1831         int loc_LightDir;
1832         int loc_LightPosition;
1833         int loc_OffsetMapping_Scale;
1834         int loc_PixelSize;
1835         int loc_ReflectColor;
1836         int loc_ReflectFactor;
1837         int loc_ReflectOffset;
1838         int loc_RefractColor;
1839         int loc_Saturation;
1840         int loc_ScreenCenterRefractReflect;
1841         int loc_ScreenScaleRefractReflect;
1842         int loc_ScreenToDepth;
1843         int loc_ShadowMap_Parameters;
1844         int loc_ShadowMap_TextureScale;
1845         int loc_SpecularPower;
1846         int loc_UserVec1;
1847         int loc_UserVec2;
1848         int loc_UserVec3;
1849         int loc_UserVec4;
1850         int loc_ViewTintColor;
1851         int loc_ViewToLight;
1852         int loc_ModelToLight;
1853         int loc_TexMatrix;
1854         int loc_BackgroundTexMatrix;
1855         int loc_ModelViewProjectionMatrix;
1856         int loc_ModelViewMatrix;
1857 }
1858 r_glsl_permutation_t;
1859
1860 #define SHADERPERMUTATION_HASHSIZE 256
1861
1862 /// information about each possible shader permutation
1863 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1864 /// currently selected permutation
1865 r_glsl_permutation_t *r_glsl_permutation;
1866 /// storage for permutations linked in the hash table
1867 memexpandablearray_t r_glsl_permutationarray;
1868
1869 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1870 {
1871         //unsigned int hashdepth = 0;
1872         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1873         r_glsl_permutation_t *p;
1874         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1875         {
1876                 if (p->mode == mode && p->permutation == permutation)
1877                 {
1878                         //if (hashdepth > 10)
1879                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1880                         return p;
1881                 }
1882                 //hashdepth++;
1883         }
1884         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1885         p->mode = mode;
1886         p->permutation = permutation;
1887         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1888         r_glsl_permutationhash[mode][hashindex] = p;
1889         //if (hashdepth > 10)
1890         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1891         return p;
1892 }
1893
1894 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1895 {
1896         char *shaderstring;
1897         if (!filename || !filename[0])
1898                 return NULL;
1899         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1900         if (shaderstring)
1901         {
1902                 if (printfromdisknotice)
1903                         Con_DPrintf("from disk %s... ", filename);
1904                 return shaderstring;
1905         }
1906         else if (!strcmp(filename, "glsl/default.glsl"))
1907         {
1908                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1909                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1910         }
1911         return shaderstring;
1912 }
1913
1914 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1915 {
1916         int i;
1917         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1918         int vertstrings_count = 0;
1919         int geomstrings_count = 0;
1920         int fragstrings_count = 0;
1921         char *vertexstring, *geometrystring, *fragmentstring;
1922         const char *vertstrings_list[32+3];
1923         const char *geomstrings_list[32+3];
1924         const char *fragstrings_list[32+3];
1925         char permutationname[256];
1926
1927         if (p->compiled)
1928                 return;
1929         p->compiled = true;
1930         p->program = 0;
1931
1932         permutationname[0] = 0;
1933         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1934         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1935         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1936
1937         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1938
1939         // the first pretext is which type of shader to compile as
1940         // (later these will all be bound together as a program object)
1941         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1942         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1943         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1944
1945         // the second pretext is the mode (for example a light source)
1946         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1947         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1948         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1949         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1950
1951         // now add all the permutation pretexts
1952         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1953         {
1954                 if (permutation & (1<<i))
1955                 {
1956                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1957                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1958                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1959                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1960                 }
1961                 else
1962                 {
1963                         // keep line numbers correct
1964                         vertstrings_list[vertstrings_count++] = "\n";
1965                         geomstrings_list[geomstrings_count++] = "\n";
1966                         fragstrings_list[fragstrings_count++] = "\n";
1967                 }
1968         }
1969
1970         // now append the shader text itself
1971         vertstrings_list[vertstrings_count++] = vertexstring;
1972         geomstrings_list[geomstrings_count++] = geometrystring;
1973         fragstrings_list[fragstrings_count++] = fragmentstring;
1974
1975         // if any sources were NULL, clear the respective list
1976         if (!vertexstring)
1977                 vertstrings_count = 0;
1978         if (!geometrystring)
1979                 geomstrings_count = 0;
1980         if (!fragmentstring)
1981                 fragstrings_count = 0;
1982
1983         // compile the shader program
1984         if (vertstrings_count + geomstrings_count + fragstrings_count)
1985                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1986         if (p->program)
1987         {
1988                 CHECKGLERROR
1989                 qglUseProgramObjectARB(p->program);CHECKGLERROR
1990                 // look up all the uniform variable names we care about, so we don't
1991                 // have to look them up every time we set them
1992
1993                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
1994                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
1995                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1996                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
1997                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
1998                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1999                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
2000                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
2001                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
2002                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
2003                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
2004                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
2005                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
2006                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
2007                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
2008                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
2009                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
2010                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
2011                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
2012                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
2013                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
2014                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
2015                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
2016                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
2017                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
2018                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
2019                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
2020                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
2021                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
2022                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
2023                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
2024                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
2025                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
2026                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
2027                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
2028                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
2029                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
2030                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
2031                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
2032                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
2033                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
2034                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
2035                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
2036                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
2037                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
2038                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
2039                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
2040                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
2041                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
2042                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
2043                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
2044                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
2045                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
2046                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
2047                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
2048                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
2049                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
2050                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
2051                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
2052                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
2053                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2054                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2055                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2056                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2057                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
2058                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
2059                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
2060                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
2061                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
2062                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
2063                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
2064                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
2065                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
2066                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
2067                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
2068                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
2069                 // initialize the samplers to refer to the texture units we use
2070                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
2071                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
2072                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
2073                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
2074                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
2075                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
2076                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
2077                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2078                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2079                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2080                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
2081                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
2082                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
2083                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
2084                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
2085                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
2086                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
2087                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
2088                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
2089                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
2090                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
2091                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
2092                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
2093                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2094                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
2095                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2096                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
2097                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2098                 CHECKGLERROR
2099                 if (developer.integer)
2100                         Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2101         }
2102         else
2103                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
2104
2105         // free the strings
2106         if (vertexstring)
2107                 Mem_Free(vertexstring);
2108         if (geometrystring)
2109                 Mem_Free(geometrystring);
2110         if (fragmentstring)
2111                 Mem_Free(fragmentstring);
2112 }
2113
2114 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
2115 {
2116         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2117         if (r_glsl_permutation != perm)
2118         {
2119                 r_glsl_permutation = perm;
2120                 if (!r_glsl_permutation->program)
2121                 {
2122                         if (!r_glsl_permutation->compiled)
2123                                 R_GLSL_CompilePermutation(perm, mode, permutation);
2124                         if (!r_glsl_permutation->program)
2125                         {
2126                                 // remove features until we find a valid permutation
2127                                 int i;
2128                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2129                                 {
2130                                         // reduce i more quickly whenever it would not remove any bits
2131                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2132                                         if (!(permutation & j))
2133                                                 continue;
2134                                         permutation -= j;
2135                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2136                                         if (!r_glsl_permutation->compiled)
2137                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
2138                                         if (r_glsl_permutation->program)
2139                                                 break;
2140                                 }
2141                                 if (i >= SHADERPERMUTATION_COUNT)
2142                                 {
2143                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2144                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2145                                         qglUseProgramObjectARB(0);CHECKGLERROR
2146                                         return; // no bit left to clear, entire mode is broken
2147                                 }
2148                         }
2149                 }
2150                 CHECKGLERROR
2151                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2152         }
2153         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
2154 }
2155
2156 #ifdef SUPPORTCG
2157 #include <Cg/cgGL.h>
2158 struct r_cg_permutation_s;
2159 typedef struct r_cg_permutation_s
2160 {
2161         /// hash lookup data
2162         struct r_cg_permutation_s *hashnext;
2163         unsigned int mode;
2164         unsigned int permutation;
2165
2166         /// indicates if we have tried compiling this permutation already
2167         qboolean compiled;
2168         /// 0 if compilation failed
2169         CGprogram vprogram;
2170         CGprogram fprogram;
2171         /// locations of detected parameters in programs, or NULL if not found
2172         CGparameter vp_EyePosition;
2173         CGparameter vp_FogPlane;
2174         CGparameter vp_LightDir;
2175         CGparameter vp_LightPosition;
2176         CGparameter vp_ModelToLight;
2177         CGparameter vp_TexMatrix;
2178         CGparameter vp_BackgroundTexMatrix;
2179         CGparameter vp_ModelViewProjectionMatrix;
2180         CGparameter vp_ModelViewMatrix;
2181
2182         CGparameter fp_Texture_First;
2183         CGparameter fp_Texture_Second;
2184         CGparameter fp_Texture_GammaRamps;
2185         CGparameter fp_Texture_Normal;
2186         CGparameter fp_Texture_Color;
2187         CGparameter fp_Texture_Gloss;
2188         CGparameter fp_Texture_Glow;
2189         CGparameter fp_Texture_SecondaryNormal;
2190         CGparameter fp_Texture_SecondaryColor;
2191         CGparameter fp_Texture_SecondaryGloss;
2192         CGparameter fp_Texture_SecondaryGlow;
2193         CGparameter fp_Texture_Pants;
2194         CGparameter fp_Texture_Shirt;
2195         CGparameter fp_Texture_FogMask;
2196         CGparameter fp_Texture_Lightmap;
2197         CGparameter fp_Texture_Deluxemap;
2198         CGparameter fp_Texture_Attenuation;
2199         CGparameter fp_Texture_Cube;
2200         CGparameter fp_Texture_Refraction;
2201         CGparameter fp_Texture_Reflection;
2202         CGparameter fp_Texture_ShadowMapRect;
2203         CGparameter fp_Texture_ShadowMapCube;
2204         CGparameter fp_Texture_ShadowMap2D;
2205         CGparameter fp_Texture_CubeProjection;
2206         CGparameter fp_Texture_ScreenDepth;
2207         CGparameter fp_Texture_ScreenNormalMap;
2208         CGparameter fp_Texture_ScreenDiffuse;
2209         CGparameter fp_Texture_ScreenSpecular;
2210         CGparameter fp_Alpha;
2211         CGparameter fp_BloomBlur_Parameters;
2212         CGparameter fp_ClientTime;
2213         CGparameter fp_Color_Ambient;
2214         CGparameter fp_Color_Diffuse;
2215         CGparameter fp_Color_Specular;
2216         CGparameter fp_Color_Glow;
2217         CGparameter fp_Color_Pants;
2218         CGparameter fp_Color_Shirt;
2219         CGparameter fp_DeferredColor_Ambient;
2220         CGparameter fp_DeferredColor_Diffuse;
2221         CGparameter fp_DeferredColor_Specular;
2222         CGparameter fp_DeferredMod_Diffuse;
2223         CGparameter fp_DeferredMod_Specular;
2224         CGparameter fp_DistortScaleRefractReflect;
2225         CGparameter fp_EyePosition;
2226         CGparameter fp_FogColor;
2227         CGparameter fp_FogHeightFade;
2228         CGparameter fp_FogPlane;
2229         CGparameter fp_FogPlaneViewDist;
2230         CGparameter fp_FogRangeRecip;
2231         CGparameter fp_LightColor;
2232         CGparameter fp_LightDir;
2233         CGparameter fp_LightPosition;
2234         CGparameter fp_OffsetMapping_Scale;
2235         CGparameter fp_PixelSize;
2236         CGparameter fp_ReflectColor;
2237         CGparameter fp_ReflectFactor;
2238         CGparameter fp_ReflectOffset;
2239         CGparameter fp_RefractColor;
2240         CGparameter fp_Saturation;
2241         CGparameter fp_ScreenCenterRefractReflect;
2242         CGparameter fp_ScreenScaleRefractReflect;
2243         CGparameter fp_ScreenToDepth;
2244         CGparameter fp_ShadowMap_Parameters;
2245         CGparameter fp_ShadowMap_TextureScale;
2246         CGparameter fp_SpecularPower;
2247         CGparameter fp_UserVec1;
2248         CGparameter fp_UserVec2;
2249         CGparameter fp_UserVec3;
2250         CGparameter fp_UserVec4;
2251         CGparameter fp_ViewTintColor;
2252         CGparameter fp_ViewToLight;
2253 }
2254 r_cg_permutation_t;
2255
2256 /// information about each possible shader permutation
2257 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
2258 /// currently selected permutation
2259 r_cg_permutation_t *r_cg_permutation;
2260 /// storage for permutations linked in the hash table
2261 memexpandablearray_t r_cg_permutationarray;
2262
2263 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
2264 {
2265         //unsigned int hashdepth = 0;
2266         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
2267         r_cg_permutation_t *p;
2268         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
2269         {
2270                 if (p->mode == mode && p->permutation == permutation)
2271                 {
2272                         //if (hashdepth > 10)
2273                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
2274                         return p;
2275                 }
2276                 //hashdepth++;
2277         }
2278         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
2279         p->mode = mode;
2280         p->permutation = permutation;
2281         p->hashnext = r_cg_permutationhash[mode][hashindex];
2282         r_cg_permutationhash[mode][hashindex] = p;
2283         //if (hashdepth > 10)
2284         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
2285         return p;
2286 }
2287
2288 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
2289 {
2290         char *shaderstring;
2291         if (!filename || !filename[0])
2292                 return NULL;
2293         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
2294         if (shaderstring)
2295         {
2296                 if (printfromdisknotice)
2297                         Con_DPrintf("from disk %s... ", filename);
2298                 return shaderstring;
2299         }
2300         else if (!strcmp(filename, "cg/default.cg"))
2301         {
2302                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
2303                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
2304         }
2305         return shaderstring;
2306 }
2307
2308 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
2309 {
2310         int i;
2311         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
2312         int vertstrings_count = 0, vertstring_length = 0;
2313         int geomstrings_count = 0, geomstring_length = 0;
2314         int fragstrings_count = 0, fragstring_length = 0;
2315         char *t;
2316         char *vertexstring, *geometrystring, *fragmentstring;
2317         char *vertstring, *geomstring, *fragstring;
2318         const char *vertstrings_list[32+3];
2319         const char *geomstrings_list[32+3];
2320         const char *fragstrings_list[32+3];
2321         char permutationname[256];
2322
2323         if (p->compiled)
2324                 return;
2325         p->compiled = true;
2326         p->vprogram = NULL;
2327         p->fprogram = NULL;
2328
2329         permutationname[0] = 0;
2330         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
2331         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
2332         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
2333
2334         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
2335
2336         // the first pretext is which type of shader to compile as
2337         // (later these will all be bound together as a program object)
2338         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
2339         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
2340         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
2341
2342         // the second pretext is the mode (for example a light source)
2343         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
2344         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
2345         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
2346         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
2347
2348         // now add all the permutation pretexts
2349         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2350         {
2351                 if (permutation & (1<<i))
2352                 {
2353                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
2354                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
2355                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
2356                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
2357                 }
2358                 else
2359                 {
2360                         // keep line numbers correct
2361                         vertstrings_list[vertstrings_count++] = "\n";
2362                         geomstrings_list[geomstrings_count++] = "\n";
2363                         fragstrings_list[fragstrings_count++] = "\n";
2364                 }
2365         }
2366
2367         // now append the shader text itself
2368         vertstrings_list[vertstrings_count++] = vertexstring;
2369         geomstrings_list[geomstrings_count++] = geometrystring;
2370         fragstrings_list[fragstrings_count++] = fragmentstring;
2371
2372         // if any sources were NULL, clear the respective list
2373         if (!vertexstring)
2374                 vertstrings_count = 0;
2375         if (!geometrystring)
2376                 geomstrings_count = 0;
2377         if (!fragmentstring)
2378                 fragstrings_count = 0;
2379
2380         vertstring_length = 0;
2381         for (i = 0;i < vertstrings_count;i++)
2382                 vertstring_length += strlen(vertstrings_list[i]);
2383         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
2384         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
2385                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
2386
2387         geomstring_length = 0;
2388         for (i = 0;i < geomstrings_count;i++)
2389                 geomstring_length += strlen(geomstrings_list[i]);
2390         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
2391         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
2392                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
2393
2394         fragstring_length = 0;
2395         for (i = 0;i < fragstrings_count;i++)
2396                 fragstring_length += strlen(fragstrings_list[i]);
2397         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
2398         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
2399                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
2400
2401         // compile the shader program
2402         if (vertstring[0] || geomstring[0] || fragstring[0])
2403         {
2404                 if (vertstring[0])
2405                         p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL);
2406                 if (fragstring[0])
2407                         p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL);
2408         }
2409
2410         if (p->vprogram)
2411         {
2412                 cgGLBindProgram(p->vprogram);
2413                 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2414         }
2415         else
2416                 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2417         if (p->fprogram)
2418         {
2419                 cgGLBindProgram(p->fprogram);
2420                 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2421         }
2422         else
2423                 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2424
2425         if (p->vprogram || p->fprogram)
2426         {
2427                 // look up all the uniform variable names we care about, so we don't
2428                 // have to look them up every time we set them
2429                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
2430                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
2431                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
2432                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
2433                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
2434                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
2435                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
2436                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
2437                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
2438
2439                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
2440                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
2441                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
2442                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
2443                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
2444                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
2445                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
2446                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
2447                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
2448                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
2449                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
2450                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
2451                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
2452                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
2453                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
2454                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
2455                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
2456                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
2457                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
2458                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
2459                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
2460                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
2461                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
2462                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
2463                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
2464                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
2465                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
2466                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
2467                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
2468                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
2469                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
2470                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
2471                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
2472                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
2473                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
2474                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
2475                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
2476                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
2477                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
2478                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
2479                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
2480                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
2481                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
2482                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
2483                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
2484                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
2485                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
2486                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
2487                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
2488                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
2489                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
2490                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
2491                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
2492                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
2493                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
2494                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
2495                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
2496                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
2497                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
2498                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
2499                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
2500                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
2501                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
2502                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
2503                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
2504                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
2505                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
2506                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
2507                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
2508                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
2509                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
2510                 CHECKGLERROR
2511                 if (developer.integer)
2512                         Con_Printf("^5CG shader %s compiled.\n", permutationname);
2513         }
2514         else
2515                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
2516
2517         // free the strings
2518         if (vertstring)
2519                 Mem_Free(vertstring);
2520         if (geomstring)
2521                 Mem_Free(geomstring);
2522         if (fragstring)
2523                 Mem_Free(fragstring);
2524         if (vertexstring)
2525                 Mem_Free(vertexstring);
2526         if (geometrystring)
2527                 Mem_Free(geometrystring);
2528         if (fragmentstring)
2529                 Mem_Free(fragmentstring);
2530 }
2531
2532 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
2533 {
2534         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
2535         if (r_cg_permutation != perm)
2536         {
2537                 r_cg_permutation = perm;
2538                 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));
2539                 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2540                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
2541                 {
2542                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2543                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2544                         if (!r_cg_permutation->compiled)
2545                                 R_CG_CompilePermutation(perm, mode, permutation);
2546                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
2547                         {
2548                                 // remove features until we find a valid permutation
2549                                 int i;
2550                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2551                                 {
2552                                         // reduce i more quickly whenever it would not remove any bits
2553                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2554                                         if (!(permutation & j))
2555                                                 continue;
2556                                         permutation -= j;
2557                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
2558                                         if (!r_cg_permutation->compiled)
2559                                                 R_CG_CompilePermutation(perm, mode, permutation);
2560                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
2561                                                 break;
2562                                 }
2563                                 if (i >= SHADERPERMUTATION_COUNT)
2564                                 {
2565                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2566                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
2567                                         return; // no bit left to clear, entire mode is broken
2568                                 }
2569                         }
2570                 }
2571                 CHECKGLERROR
2572                 if (r_cg_permutation->vprogram)
2573                 {
2574                         cgGLBindProgram(r_cg_permutation->vprogram);
2575                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2576                 }
2577                 else
2578                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2579                 if (r_cg_permutation->fprogram)
2580                 {
2581                         cgGLBindProgram(r_cg_permutation->fprogram);
2582                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2583                 }
2584                 else
2585                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2586         }
2587         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);
2588 }
2589 #endif
2590
2591 void R_GLSL_Restart_f(void)
2592 {
2593         unsigned int i, limit;
2594         r_glsl_permutation_t *p;
2595         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2596         for (i = 0;i < limit;i++)
2597         {
2598                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2599                 {
2600                         GL_Backend_FreeProgram(p->program);
2601                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2602                 }
2603         }
2604         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2605 #ifdef SUPPORTCG
2606         if (vid.cgcontext)
2607         {
2608                 r_cg_permutation_t *p;
2609                 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
2610                 for (i = 0;i < limit;i++)
2611                 {
2612                         if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
2613                         {
2614                                 if (p->vprogram)
2615                                         cgDestroyProgram(p->vprogram);
2616                                 if (p->fprogram)
2617                                         cgDestroyProgram(p->fprogram);
2618                                 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
2619                         }
2620                 }
2621                 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
2622         }
2623 #endif
2624 }
2625
2626 void R_GLSL_DumpShader_f(void)
2627 {
2628         int i;
2629         qfile_t *file;
2630
2631         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2632         if (file)
2633         {
2634                 FS_Print(file, "/* The engine may define the following macros:\n");
2635                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2636                 for (i = 0;i < SHADERMODE_COUNT;i++)
2637                         FS_Print(file, glslshadermodeinfo[i].pretext);
2638                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2639                         FS_Print(file, shaderpermutationinfo[i].pretext);
2640                 FS_Print(file, "*/\n");
2641                 FS_Print(file, builtinshaderstring);
2642                 FS_Close(file);
2643                 Con_Printf("glsl/default.glsl written\n");
2644         }
2645         else
2646                 Con_Printf("failed to write to glsl/default.glsl\n");
2647
2648 #ifdef SUPPORTCG
2649         file = FS_OpenRealFile("cg/default.cg", "w", false);
2650         if (file)
2651         {
2652                 FS_Print(file, "/* The engine may define the following macros:\n");
2653                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2654                 for (i = 0;i < SHADERMODE_COUNT;i++)
2655                         FS_Print(file, cgshadermodeinfo[i].pretext);
2656                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2657                         FS_Print(file, shaderpermutationinfo[i].pretext);
2658                 FS_Print(file, "*/\n");
2659                 FS_Print(file, builtincgshaderstring);
2660                 FS_Close(file);
2661                 Con_Printf("cg/default.cg written\n");
2662         }
2663         else
2664                 Con_Printf("failed to write to cg/default.cg\n");
2665 #endif
2666 }
2667
2668 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
2669 {
2670         if (!second)
2671                 texturemode = GL_MODULATE;
2672         switch (vid.renderpath)
2673         {
2674         case RENDERPATH_GL20:
2675                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
2676                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(first ));
2677                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, R_GetTexture(second));
2678                 break;
2679         case RENDERPATH_CGGL:
2680                 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                 break;
2684         case RENDERPATH_GL13:
2685                 R_Mesh_TexBind(0, R_GetTexture(first ));
2686                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2687                 R_Mesh_TexBind(1, R_GetTexture(second));
2688                 if (second)
2689                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2690                 break;
2691         case RENDERPATH_GL11:
2692                 R_Mesh_TexBind(0, R_GetTexture(first ));
2693                 break;
2694         }
2695 }
2696
2697 void R_SetupShader_DepthOrShadow(void)
2698 {
2699         switch (vid.renderpath)
2700         {
2701         case RENDERPATH_GL20:
2702                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
2703                 break;
2704         case RENDERPATH_CGGL:
2705                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
2706                 break;
2707         case RENDERPATH_GL13:
2708                 R_Mesh_TexBind(0, 0);
2709                 R_Mesh_TexBind(1, 0);
2710                 break;
2711         case RENDERPATH_GL11:
2712                 R_Mesh_TexBind(0, 0);
2713                 break;
2714         }
2715 }
2716
2717 void R_SetupShader_ShowDepth(void)
2718 {
2719         switch (vid.renderpath)
2720         {
2721         case RENDERPATH_GL20:
2722                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
2723                 break;
2724         case RENDERPATH_CGGL:
2725                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
2726                 break;
2727         case RENDERPATH_GL13:
2728                 break;
2729         case RENDERPATH_GL11:
2730                 break;
2731         }
2732 }
2733
2734 extern qboolean r_shadow_usingdeferredprepass;
2735 extern cvar_t r_shadow_deferred_8bitrange;
2736 extern rtexture_t *r_shadow_attenuationgradienttexture;
2737 extern rtexture_t *r_shadow_attenuation2dtexture;
2738 extern rtexture_t *r_shadow_attenuation3dtexture;
2739 extern qboolean r_shadow_usingshadowmaprect;
2740 extern qboolean r_shadow_usingshadowmapcube;
2741 extern qboolean r_shadow_usingshadowmap2d;
2742 extern float r_shadow_shadowmap_texturescale[2];
2743 extern float r_shadow_shadowmap_parameters[4];
2744 extern qboolean r_shadow_shadowmapvsdct;
2745 extern qboolean r_shadow_shadowmapsampler;
2746 extern int r_shadow_shadowmappcf;
2747 extern rtexture_t *r_shadow_shadowmaprectangletexture;
2748 extern rtexture_t *r_shadow_shadowmap2dtexture;
2749 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
2750 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2751 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2752 extern int r_shadow_prepass_width;
2753 extern int r_shadow_prepass_height;
2754 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2755 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2756 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2757 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2758 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2759 {
2760         // select a permutation of the lighting shader appropriate to this
2761         // combination of texture, entity, light source, and fogging, only use the
2762         // minimum features necessary to avoid wasting rendering time in the
2763         // fragment shader on features that are not being used
2764         unsigned int permutation = 0;
2765         unsigned int mode = 0;
2766         float m16f[16];
2767         // TODO: implement geometry-shader based shadow volumes someday
2768         if (r_glsl_offsetmapping.integer)
2769         {
2770                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2771                 if (r_glsl_offsetmapping_reliefmapping.integer)
2772                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2773         }
2774         if (rsurfacepass == RSURFPASS_BACKGROUND)
2775         {
2776                 // distorted background
2777                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2778                         mode = SHADERMODE_WATER;
2779                 else
2780                         mode = SHADERMODE_REFRACTION;
2781         }
2782         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2783         {
2784                 // normalmap (deferred prepass), may use alpha test on diffuse
2785                 mode = SHADERMODE_DEFERREDGEOMETRY;
2786                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2787                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2788                 if (r_glsl_offsetmapping.integer)
2789                 {
2790                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2791                         if (r_glsl_offsetmapping_reliefmapping.integer)
2792                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2793                 }
2794         }
2795         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2796         {
2797                 // light source
2798                 mode = SHADERMODE_LIGHTSOURCE;
2799                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2800                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2801                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2802                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2803                 if (diffusescale > 0)
2804                         permutation |= SHADERPERMUTATION_DIFFUSE;
2805                 if (specularscale > 0)
2806                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2807                 if (r_refdef.fogenabled)
2808                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2809                 if (rsurface.texture->colormapping)
2810                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2811                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2812                 {
2813                         if (r_shadow_usingshadowmaprect)
2814                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2815                         if (r_shadow_usingshadowmap2d)
2816                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2817                         if (r_shadow_usingshadowmapcube)
2818                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2819                         else if(r_shadow_shadowmapvsdct)
2820                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2821
2822                         if (r_shadow_shadowmapsampler)
2823                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2824                         if (r_shadow_shadowmappcf > 1)
2825                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2826                         else if (r_shadow_shadowmappcf)
2827                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2828                 }
2829         }
2830         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2831         {
2832                 // unshaded geometry (fullbright or ambient model lighting)
2833                 mode = SHADERMODE_FLATCOLOR;
2834                 ambientscale = diffusescale = specularscale = 0;
2835                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2836                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2837                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2838                         permutation |= SHADERPERMUTATION_GLOW;
2839                 if (r_refdef.fogenabled)
2840                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2841                 if (rsurface.texture->colormapping)
2842                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2843                 if (r_glsl_offsetmapping.integer)
2844                 {
2845                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2846                         if (r_glsl_offsetmapping_reliefmapping.integer)
2847                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2848                 }
2849                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2850                         permutation |= SHADERPERMUTATION_REFLECTION;
2851         }
2852         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2853         {
2854                 // directional model lighting
2855                 mode = SHADERMODE_LIGHTDIRECTION;
2856                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2857                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2858                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2859                         permutation |= SHADERPERMUTATION_GLOW;
2860                 permutation |= SHADERPERMUTATION_DIFFUSE;
2861                 if (specularscale > 0)
2862                         permutation |= SHADERPERMUTATION_SPECULAR;
2863                 if (r_refdef.fogenabled)
2864                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2865                 if (rsurface.texture->colormapping)
2866                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2867                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2868                         permutation |= SHADERPERMUTATION_REFLECTION;
2869                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2870                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2871         }
2872         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2873         {
2874                 // ambient model lighting
2875                 mode = SHADERMODE_LIGHTDIRECTION;
2876                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2877                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2878                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2879                         permutation |= SHADERPERMUTATION_GLOW;
2880                 if (r_refdef.fogenabled)
2881                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2882                 if (rsurface.texture->colormapping)
2883                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2884                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2885                         permutation |= SHADERPERMUTATION_REFLECTION;
2886                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2887                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2888         }
2889         else
2890         {
2891                 // lightmapped wall
2892                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2893                 {
2894                         // deluxemapping (light direction texture)
2895                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2896                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2897                         else
2898                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2899                         permutation |= SHADERPERMUTATION_DIFFUSE;
2900                         if (specularscale > 0)
2901                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2902                 }
2903                 else if (r_glsl_deluxemapping.integer >= 2)
2904                 {
2905                         // fake deluxemapping (uniform light direction in tangentspace)
2906                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2907                         permutation |= SHADERPERMUTATION_DIFFUSE;
2908                         if (specularscale > 0)
2909                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2910                 }
2911                 else if (rsurface.uselightmaptexture)
2912                 {
2913                         // ordinary lightmapping (q1bsp, q3bsp)
2914                         mode = SHADERMODE_LIGHTMAP;
2915                 }
2916                 else
2917                 {
2918                         // ordinary vertex coloring (q3bsp)
2919                         mode = SHADERMODE_VERTEXCOLOR;
2920                 }
2921                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2922                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2923                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2924                         permutation |= SHADERPERMUTATION_GLOW;
2925                 if (r_refdef.fogenabled)
2926                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2927                 if (rsurface.texture->colormapping)
2928                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2929                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2930                         permutation |= SHADERPERMUTATION_REFLECTION;
2931                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2932                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2933         }
2934         if(permutation & SHADERPERMUTATION_SPECULAR)
2935                 if(r_shadow_glossexact.integer)
2936                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2937         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
2938                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2939         switch(vid.renderpath)
2940         {
2941         case RENDERPATH_GL20:
2942                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2943                 if (mode == SHADERMODE_LIGHTSOURCE)
2944                 {
2945                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2946                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2947                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2948                         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);
2949                         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);
2950                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
2951         
2952                         // additive passes are only darkened by fog, not tinted
2953                         if (r_glsl_permutation->loc_FogColor >= 0)
2954                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2955                         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]);
2956                         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]);
2957                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2958                 }
2959                 else
2960                 {
2961                         if (mode == SHADERMODE_FLATCOLOR)
2962                         {
2963                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
2964                         }
2965                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2966                         {
2967                                 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]);
2968                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
2969                                 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);
2970                                 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);
2971                                 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);
2972                                 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]);
2973                                 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]);
2974                         }
2975                         else
2976                         {
2977                                 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]);
2978                                 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]);
2979                                 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);
2980                                 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);
2981                                 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);
2982                         }
2983                         // additive passes are only darkened by fog, not tinted
2984                         if (r_glsl_permutation->loc_FogColor >= 0)
2985                         {
2986                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2987                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2988                                 else
2989                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2990                         }
2991                         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);
2992                         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]);
2993                         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]);
2994                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2995                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2996                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2997                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2998                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2999                 }
3000                 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3001                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
3002                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
3003                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3004                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
3005                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3006                 if (r_glsl_permutation->loc_Color_Pants >= 0)
3007                 {
3008                         if (rsurface.texture->pantstexture)
3009                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3010                         else
3011                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
3012                 }
3013                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
3014                 {
3015                         if (rsurface.texture->shirttexture)
3016                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3017                         else
3018                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
3019                 }
3020                 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]);
3021                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
3022                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
3023                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
3024                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
3025                 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]);
3026
3027         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             ,          R_GetTexture(r_texture_white                                     ));
3028         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            ,          R_GetTexture(r_texture_white                                     ));
3029         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        ,          R_GetTexture(r_texture_gammaramps                                ));
3030                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            ,          R_GetTexture(rsurface.texture->nmaptexture                       ));
3031                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             ,          R_GetTexture(rsurface.texture->basetexture                       ));
3032                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             ,          R_GetTexture(rsurface.texture->glosstexture                      ));
3033                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              ,          R_GetTexture(rsurface.texture->glowtexture                       ));
3034                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  ,          R_GetTexture(rsurface.texture->backgroundnmaptexture             ));
3035                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   ,          R_GetTexture(rsurface.texture->backgroundbasetexture             ));
3036                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   ,          R_GetTexture(rsurface.texture->backgroundglosstexture            ));
3037                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    ,          R_GetTexture(rsurface.texture->backgroundglowtexture             ));
3038                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             ,          R_GetTexture(rsurface.texture->pantstexture                      ));
3039                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             ,          R_GetTexture(rsurface.texture->shirttexture                      ));
3040                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           ,          R_GetTexture(r_texture_fogattenuation                            ));
3041                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          ,          R_GetTexture(r_texture_white                                     ));
3042                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          ,          R_GetTexture(r_texture_blanknormalmap                            ));
3043                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       ,          R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3044                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        ,          R_GetTexture(r_texture_white                                     ));
3045                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        ,          R_GetTexture(r_texture_white                                     ));
3046                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH    , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3047                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3048                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE  , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture              ));
3049                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture             ));
3050                 if (rsurface.rtlight)
3051                 {
3052                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBindAll(GL20TU_CUBE           , 0, 0,    R_GetTexture(rsurface.rtlight->currentcubemap                    ), 0);
3053                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT  , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3054                         if (r_shadow_usingshadowmapcube)
3055                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE  , 0, 0,    R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
3056                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       ,          R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3057                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0,    R_GetTexture(r_shadow_shadowmapvsdcttexture                      ), 0);
3058                 }
3059                 CHECKGLERROR
3060                 break;
3061         case RENDERPATH_CGGL:
3062 #ifdef SUPPORTCG
3063                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3064                 if (mode == SHADERMODE_LIGHTSOURCE)
3065                 {
3066                         if (r_cg_permutation->vp_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}
3067                         if (r_cg_permutation->vp_LightPosition >= 0) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
3068                 }
3069                 else
3070                 {
3071                         if (mode == SHADERMODE_LIGHTDIRECTION)
3072                         {
3073                                 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]);
3074                         }
3075                 }
3076                 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);
3077                 if (r_cg_permutation->vp_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}
3078                 if (r_cg_permutation->vp_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}
3079                 if (r_cg_permutation->vp_EyePosition >= 0) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3080                 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]);
3081                 CHECKGLERROR
3082
3083                 if (mode == SHADERMODE_LIGHTSOURCE)
3084                 {
3085                         if (r_cg_permutation->fp_LightPosition >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
3086                         if (r_cg_permutation->fp_LightColor >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
3087                         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);
3088                         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);
3089                         if (r_cg_permutation->fp_Color_Specular >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);
3090
3091                         // additive passes are only darkened by fog, not tinted
3092                         if (r_cg_permutation->fp_FogColor >= 0)
3093                                 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
3094                         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]);
3095                         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]);
3096                         if (r_cg_permutation->fp_SpecularPower >= 0) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3097                 }
3098                 else
3099                 {
3100                         if (mode == SHADERMODE_FLATCOLOR)
3101                         {
3102                                 if (r_cg_permutation->fp_Color_Ambient >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
3103                         }
3104                         else if (mode == SHADERMODE_LIGHTDIRECTION)
3105                         {
3106                                 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]);
3107                                 if (r_cg_permutation->fp_Color_Diffuse >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
3108                                 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);
3109                                 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);
3110                                 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);
3111                                 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]);
3112                                 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]);
3113                         }
3114                         else
3115                         {
3116                                 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]);
3117                                 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]);
3118                                 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);
3119                                 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);
3120                                 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);
3121                         }
3122                         // additive passes are only darkened by fog, not tinted
3123                         if (r_cg_permutation->fp_FogColor >= 0)
3124                         {
3125                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
3126                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
3127                                 else
3128                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
3129                         }
3130                         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);
3131                         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]);
3132                         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]);
3133                         if (r_cg_permutation->fp_RefractColor >= 0) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);
3134                         if (r_cg_permutation->fp_ReflectColor >= 0) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);
3135                         if (r_cg_permutation->fp_ReflectFactor >= 0) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3136                         if (r_cg_permutation->fp_ReflectOffset >= 0) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);
3137                         if (r_cg_permutation->fp_SpecularPower >= 0) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3138                 }
3139                 if (r_cg_permutation->fp_Color_Glow >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3140                 if (r_cg_permutation->fp_Alpha >= 0) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);
3141                 if (r_cg_permutation->fp_EyePosition >= 0) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3142                 if (r_cg_permutation->fp_Color_Pants >= 0)
3143                 {
3144                         if (rsurface.texture->pantstexture)
3145                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3146                         else
3147                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
3148                 }
3149                 if (r_cg_permutation->fp_Color_Shirt >= 0)
3150                 {
3151                         if (rsurface.texture->shirttexture)
3152                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3153                         else
3154                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
3155                 }
3156                 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]);
3157                 if (r_cg_permutation->fp_FogPlaneViewDist >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);
3158                 if (r_cg_permutation->fp_FogRangeRecip >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);
3159                 if (r_cg_permutation->fp_FogHeightFade >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);
3160                 if (r_cg_permutation->fp_OffsetMapping_Scale >= 0) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
3161                 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]);
3162
3163         //      if (r_cg_permutation->fp_Texture_First          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First          , R_GetTexture(r_texture_white                                     ));
3164         //      if (r_cg_permutation->fp_Texture_Second         ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second         , R_GetTexture(r_texture_white                                     ));
3165         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_GammaRamps     , R_GetTexture(r_texture_gammaramps                                ));
3166                 if (r_cg_permutation->fp_Texture_Normal         ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Normal         , R_GetTexture(rsurface.texture->nmaptexture                       ));
3167                 if (r_cg_permutation->fp_Texture_Color          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Color          , R_GetTexture(rsurface.texture->basetexture                       ));
3168                 if (r_cg_permutation->fp_Texture_Gloss          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Gloss          , R_GetTexture(rsurface.texture->glosstexture                      ));
3169                 if (r_cg_permutation->fp_Texture_Glow           ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Glow           , R_GetTexture(rsurface.texture->glowtexture                       ));
3170                 if (r_cg_permutation->fp_Texture_SecondaryNormal) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryNormal, R_GetTexture(rsurface.texture->backgroundnmaptexture             ));
3171                 if (r_cg_permutation->fp_Texture_SecondaryColor ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryColor , R_GetTexture(rsurface.texture->backgroundbasetexture             ));
3172                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryGloss , R_GetTexture(rsurface.texture->backgroundglosstexture            ));
3173                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryGlow  , R_GetTexture(rsurface.texture->backgroundglowtexture             ));
3174                 if (r_cg_permutation->fp_Texture_Pants          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Pants          , R_GetTexture(rsurface.texture->pantstexture                      ));
3175                 if (r_cg_permutation->fp_Texture_Shirt          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Shirt          , R_GetTexture(rsurface.texture->shirttexture                      ));
3176                 if (r_cg_permutation->fp_Texture_FogMask        ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_FogMask        , R_GetTexture(r_texture_fogattenuation                            ));
3177                 if (r_cg_permutation->fp_Texture_Lightmap       ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Lightmap       , R_GetTexture(r_texture_white                                     ));
3178                 if (r_cg_permutation->fp_Texture_Deluxemap      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Deluxemap      , R_GetTexture(r_texture_blanknormalmap                            ));
3179                 if (r_cg_permutation->fp_Texture_Attenuation    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Attenuation    , R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3180                 if (r_cg_permutation->fp_Texture_Refraction     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Refraction     , R_GetTexture(r_texture_white                                     ));
3181                 if (r_cg_permutation->fp_Texture_Reflection     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Reflection     , R_GetTexture(r_texture_white                                     ));
3182                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDepth    , R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3183                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3184                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDiffuse  , R_GetTexture(r_shadow_prepasslightingdiffusetexture              ));
3185                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenSpecular , R_GetTexture(r_shadow_prepasslightingspeculartexture             ));
3186                 if (rsurface.rtlight)
3187                 {
3188                         if (r_cg_permutation->fp_Texture_Cube       ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Cube           , R_GetTexture(rsurface.rtlight->currentcubemap                    ));
3189                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapRect  , R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3190                         if (r_shadow_usingshadowmapcube)
3191                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapCube  , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
3192                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMap2D    , R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3193                         if (r_cg_permutation->fp_Texture_CubeProjection ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture                      ));
3194                 }
3195
3196                 CHECKGLERROR
3197 #endif
3198                 break;
3199         case RENDERPATH_GL13:
3200         case RENDERPATH_GL11:
3201                 break;
3202         }
3203 }
3204
3205 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3206 {
3207         // select a permutation of the lighting shader appropriate to this
3208         // combination of texture, entity, light source, and fogging, only use the
3209         // minimum features necessary to avoid wasting rendering time in the
3210         // fragment shader on features that are not being used
3211         unsigned int permutation = 0;
3212         unsigned int mode = 0;
3213         const float *lightcolorbase = rtlight->currentcolor;
3214         float ambientscale = rtlight->ambientscale;
3215         float diffusescale = rtlight->diffusescale;
3216         float specularscale = rtlight->specularscale;
3217         // this is the location of the light in view space
3218         vec3_t viewlightorigin;
3219         // this transforms from view space (camera) to light space (cubemap)
3220         matrix4x4_t viewtolight;
3221         matrix4x4_t lighttoview;
3222         float viewtolight16f[16];
3223         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3224         // light source
3225         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3226         if (rtlight->currentcubemap != r_texture_whitecube)
3227                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3228         if (diffusescale > 0)
3229                 permutation |= SHADERPERMUTATION_DIFFUSE;
3230         if (specularscale > 0)
3231         {
3232                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3233                 if (r_shadow_glossexact.integer)
3234                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
3235         }
3236         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
3237         {
3238                 if (r_shadow_usingshadowmaprect)
3239                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
3240                 if (r_shadow_usingshadowmap2d)
3241                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3242                 if (r_shadow_usingshadowmapcube)
3243                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
3244                 else if(r_shadow_shadowmapvsdct)
3245                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3246
3247                 if (r_shadow_shadowmapsampler)
3248                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3249                 if (r_shadow_shadowmappcf > 1)
3250                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3251                 else if (r_shadow_shadowmappcf)
3252                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3253         }
3254         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3255         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3256         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3257         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3258         switch(vid.renderpath)
3259         {
3260         case RENDERPATH_GL20:
3261                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3262                 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3263                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3264                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3265                 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);
3266                 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);
3267                 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);
3268                 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]);
3269                 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]);
3270                 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));
3271                 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]);
3272
3273                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       ,          R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3274                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH    , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3275                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3276                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBindAll(GL20TU_CUBE           , 0, 0,    R_GetTexture(rsurface.rtlight->currentcubemap                    ), 0);
3277                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT  , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3278                 if (r_shadow_usingshadowmapcube)
3279                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE  , 0, 0,    R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
3280                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       ,          R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3281                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0,    R_GetTexture(r_shadow_shadowmapvsdcttexture                      ), 0);
3282                 break;
3283         case RENDERPATH_CGGL:
3284 #ifdef SUPPORTCG
3285                 R_SetupShader_SetPermutationCG(mode, permutation);
3286                 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);
3287                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3288                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);
3289                 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);
3290                 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);
3291                 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);
3292                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3293                 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]);
3294                 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));
3295                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3296
3297                 if (r_cg_permutation->fp_Texture_Attenuation      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Attenuation    , R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3298                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDepth    , R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3299                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3300                 if (r_cg_permutation->fp_Texture_Cube             ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Cube           , R_GetTexture(rsurface.rtlight->currentcubemap                    ));
3301                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapRect  , R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3302                 if (r_shadow_usingshadowmapcube)
3303                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapCube  , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
3304                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMap2D    , R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3305                 if (r_cg_permutation->fp_Texture_CubeProjection   ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture                      ));
3306 #endif
3307                 break;
3308         case RENDERPATH_GL13:
3309         case RENDERPATH_GL11:
3310                 break;
3311         }
3312 }
3313
3314 #define SKINFRAME_HASH 1024
3315
3316 typedef struct
3317 {
3318         int loadsequence; // incremented each level change
3319         memexpandablearray_t array;
3320         skinframe_t *hash[SKINFRAME_HASH];
3321 }
3322 r_skinframe_t;
3323 r_skinframe_t r_skinframe;
3324
3325 void R_SkinFrame_PrepareForPurge(void)
3326 {
3327         r_skinframe.loadsequence++;
3328         // wrap it without hitting zero
3329         if (r_skinframe.loadsequence >= 200)
3330                 r_skinframe.loadsequence = 1;
3331 }
3332
3333 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3334 {
3335         if (!skinframe)
3336                 return;
3337         // mark the skinframe as used for the purging code
3338         skinframe->loadsequence = r_skinframe.loadsequence;
3339 }
3340
3341 void R_SkinFrame_Purge(void)
3342 {
3343         int i;
3344         skinframe_t *s;
3345         for (i = 0;i < SKINFRAME_HASH;i++)
3346         {
3347                 for (s = r_skinframe.hash[i];s;s = s->next)
3348                 {
3349                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3350                         {
3351                                 if (s->merged == s->base)
3352                                         s->merged = NULL;
3353                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3354                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3355                                 R_PurgeTexture(s->merged);s->merged = NULL;
3356                                 R_PurgeTexture(s->base  );s->base   = NULL;
3357                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3358                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3359                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3360                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3361                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3362                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3363                                 s->loadsequence = 0;
3364                         }
3365                 }
3366         }
3367 }
3368
3369 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3370         skinframe_t *item;
3371         char basename[MAX_QPATH];
3372
3373         Image_StripImageExtension(name, basename, sizeof(basename));
3374
3375         if( last == NULL ) {
3376                 int hashindex;
3377                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3378                 item = r_skinframe.hash[hashindex];
3379         } else {
3380                 item = last->next;
3381         }
3382
3383         // linearly search through the hash bucket
3384         for( ; item ; item = item->next ) {
3385                 if( !strcmp( item->basename, basename ) ) {
3386                         return item;
3387                 }
3388         }
3389         return NULL;
3390 }
3391
3392 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3393 {
3394         skinframe_t *item;
3395         int hashindex;
3396         char basename[MAX_QPATH];
3397
3398         Image_StripImageExtension(name, basename, sizeof(basename));
3399
3400         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3401         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3402                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3403                         break;
3404
3405         if (!item) {
3406                 rtexture_t *dyntexture;
3407                 // check whether its a dynamic texture
3408                 dyntexture = CL_GetDynTexture( basename );
3409                 if (!add && !dyntexture)
3410                         return NULL;
3411                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3412                 memset(item, 0, sizeof(*item));
3413                 strlcpy(item->basename, basename, sizeof(item->basename));
3414                 item->base = dyntexture; // either NULL or dyntexture handle
3415                 item->textureflags = textureflags;
3416                 item->comparewidth = comparewidth;
3417                 item->compareheight = compareheight;
3418                 item->comparecrc = comparecrc;
3419                 item->next = r_skinframe.hash[hashindex];
3420                 r_skinframe.hash[hashindex] = item;
3421         }
3422         else if( item->base == NULL )
3423         {
3424                 rtexture_t *dyntexture;
3425                 // check whether its a dynamic texture
3426                 // 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]
3427                 dyntexture = CL_GetDynTexture( basename );
3428                 item->base = dyntexture; // either NULL or dyntexture handle
3429         }
3430
3431         R_SkinFrame_MarkUsed(item);
3432         return item;
3433 }
3434
3435 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3436         { \
3437                 unsigned long long avgcolor[5], wsum; \
3438                 int pix, comp, w; \
3439                 avgcolor[0] = 0; \
3440                 avgcolor[1] = 0; \
3441                 avgcolor[2] = 0; \
3442                 avgcolor[3] = 0; \
3443                 avgcolor[4] = 0; \
3444                 wsum = 0; \
3445                 for(pix = 0; pix < cnt; ++pix) \
3446                 { \
3447                         w = 0; \
3448                         for(comp = 0; comp < 3; ++comp) \
3449                                 w += getpixel; \
3450                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3451                         { \
3452                                 ++wsum; \
3453                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3454                                 w = getpixel; \
3455                                 for(comp = 0; comp < 3; ++comp) \
3456                                         avgcolor[comp] += getpixel * w; \
3457                                 avgcolor[3] += w; \
3458                         } \
3459                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3460                         avgcolor[4] += getpixel; \
3461                 } \
3462                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3463                         avgcolor[3] = 1; \
3464                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3465                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3466                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3467                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3468         }
3469
3470 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3471 {
3472         int j;
3473         unsigned char *pixels;
3474         unsigned char *bumppixels;
3475         unsigned char *basepixels = NULL;
3476         int basepixels_width;
3477         int basepixels_height;
3478         skinframe_t *skinframe;
3479
3480         if (cls.state == ca_dedicated)
3481                 return NULL;
3482
3483         // return an existing skinframe if already loaded
3484         // if loading of the first image fails, don't make a new skinframe as it
3485         // would cause all future lookups of this to be missing
3486         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3487         if (skinframe && skinframe->base)
3488                 return skinframe;
3489
3490         basepixels = loadimagepixelsbgra(name, complain, true);
3491         if (basepixels == NULL)
3492                 return NULL;
3493
3494         if (developer_loading.integer)
3495                 Con_Printf("loading skin \"%s\"\n", name);
3496
3497         // we've got some pixels to store, so really allocate this new texture now
3498         if (!skinframe)
3499                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3500         skinframe->stain = NULL;
3501         skinframe->merged = NULL;
3502         skinframe->base = r_texture_notexture;
3503         skinframe->pants = NULL;
3504         skinframe->shirt = NULL;
3505         skinframe->nmap = r_texture_blanknormalmap;
3506         skinframe->gloss = NULL;
3507         skinframe->glow = NULL;
3508         skinframe->fog = NULL;
3509         skinframe->hasalpha = false;
3510
3511         basepixels_width = image_width;
3512         basepixels_height = image_height;
3513         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);
3514
3515         if (textureflags & TEXF_ALPHA)
3516         {
3517                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3518                 {
3519                         if (basepixels[j] < 255)
3520                         {
3521                                 skinframe->hasalpha = true;
3522                                 break;
3523                         }
3524                 }
3525                 if (r_loadfog && skinframe->hasalpha)
3526                 {
3527                         // has transparent pixels
3528                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3529                         for (j = 0;j < image_width * image_height * 4;j += 4)
3530                         {
3531                                 pixels[j+0] = 255;
3532                                 pixels[j+1] = 255;
3533                                 pixels[j+2] = 255;
3534                                 pixels[j+3] = basepixels[j+3];
3535                         }
3536                         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);
3537                         Mem_Free(pixels);
3538                 }
3539         }
3540
3541         R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3542         //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]);
3543
3544         // _norm is the name used by tenebrae and has been adopted as standard
3545         if (r_loadnormalmap)
3546         {
3547                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
3548                 {
3549                         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);
3550                         Mem_Free(pixels);
3551                         pixels = NULL;
3552                 }
3553                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
3554                 {
3555                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3556                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3557                         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);
3558                         Mem_Free(pixels);
3559                         Mem_Free(bumppixels);
3560                 }
3561                 else if (r_shadow_bumpscale_basetexture.value > 0)
3562                 {
3563                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3564                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3565                         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);
3566                         Mem_Free(pixels);
3567                 }
3568         }
3569         // _luma is supported for tenebrae compatibility
3570         // (I think it's a very stupid name, but oh well)
3571         // _glow is the preferred name
3572         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;}
3573         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;}
3574         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;}
3575         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;}
3576
3577         if (basepixels)
3578                 Mem_Free(basepixels);
3579
3580         return skinframe;
3581 }
3582
3583 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3584 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3585 {
3586         int i;
3587         unsigned char *temp1, *temp2;
3588         skinframe_t *skinframe;
3589
3590         if (cls.state == ca_dedicated)
3591                 return NULL;
3592
3593         // if already loaded just return it, otherwise make a new skinframe
3594         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3595         if (skinframe && skinframe->base)
3596                 return skinframe;
3597
3598         skinframe->stain = NULL;
3599         skinframe->merged = NULL;
3600         skinframe->base = r_texture_notexture;
3601         skinframe->pants = NULL;
3602         skinframe->shirt = NULL;
3603         skinframe->nmap = r_texture_blanknormalmap;
3604         skinframe->gloss = NULL;
3605         skinframe->glow = NULL;
3606         skinframe->fog = NULL;
3607         skinframe->hasalpha = false;
3608
3609         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3610         if (!skindata)
3611                 return NULL;
3612
3613         if (developer_loading.integer)
3614                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3615
3616         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3617         {
3618                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3619                 temp2 = temp1 + width * height * 4;
3620                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3621                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3622                 Mem_Free(temp1);
3623         }
3624         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
3625         if (textureflags & TEXF_ALPHA)
3626         {
3627                 for (i = 3;i < width * height * 4;i += 4)
3628                 {
3629                         if (skindata[i] < 255)
3630                         {
3631                                 skinframe->hasalpha = true;
3632                                 break;
3633                         }
3634                 }
3635                 if (r_loadfog && skinframe->hasalpha)
3636                 {
3637                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3638                         memcpy(fogpixels, skindata, width * height * 4);
3639                         for (i = 0;i < width * height * 4;i += 4)
3640                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3641                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
3642                         Mem_Free(fogpixels);
3643                 }
3644         }
3645
3646         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3647         //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]);
3648
3649         return skinframe;
3650 }
3651
3652 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3653 {
3654         int i;
3655         int featuresmask;
3656         skinframe_t *skinframe;
3657
3658         if (cls.state == ca_dedicated)
3659                 return NULL;
3660
3661         // if already loaded just return it, otherwise make a new skinframe
3662         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3663         if (skinframe && skinframe->base)
3664                 return skinframe;
3665
3666         skinframe->stain = NULL;
3667         skinframe->merged = NULL;
3668         skinframe->base = r_texture_notexture;
3669         skinframe->pants = NULL;
3670         skinframe->shirt = NULL;
3671         skinframe->nmap = r_texture_blanknormalmap;
3672         skinframe->gloss = NULL;
3673         skinframe->glow = NULL;
3674         skinframe->fog = NULL;
3675         skinframe->hasalpha = false;
3676
3677         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3678         if (!skindata)
3679                 return NULL;
3680
3681         if (developer_loading.integer)
3682                 Con_Printf("loading quake skin \"%s\"\n", name);
3683
3684         // 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)
3685         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
3686         memcpy(skinframe->qpixels, skindata, width*height);
3687         skinframe->qwidth = width;
3688         skinframe->qheight = height;
3689
3690         featuresmask = 0;
3691         for (i = 0;i < width * height;i++)
3692                 featuresmask |= palette_featureflags[skindata[i]];
3693
3694         skinframe->hasalpha = false;
3695         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3696         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3697         skinframe->qgeneratemerged = true;
3698         skinframe->qgeneratebase = skinframe->qhascolormapping;
3699         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3700
3701         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3702         //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]);
3703
3704         return skinframe;
3705 }
3706
3707 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3708 {
3709         int width;
3710         int height;
3711         unsigned char *skindata;
3712
3713         if (!skinframe->qpixels)
3714                 return;
3715
3716         if (!skinframe->qhascolormapping)
3717                 colormapped = false;
3718
3719         if (colormapped)
3720         {
3721                 if (!skinframe->qgeneratebase)
3722                         return;
3723         }
3724         else
3725         {
3726                 if (!skinframe->qgeneratemerged)
3727                         return;
3728         }
3729
3730         width = skinframe->qwidth;
3731         height = skinframe->qheight;
3732         skindata = skinframe->qpixels;
3733
3734         if (skinframe->qgeneratenmap)
3735         {
3736                 unsigned char *temp1, *temp2;
3737                 skinframe->qgeneratenmap = false;
3738                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3739                 temp2 = temp1 + width * height * 4;
3740                 // use either a custom palette or the quake palette
3741                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3742                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3743                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3744                 Mem_Free(temp1);
3745         }
3746
3747         if (skinframe->qgenerateglow)
3748         {
3749                 skinframe->qgenerateglow = false;
3750                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
3751         }
3752
3753         if (colormapped)
3754         {
3755                 skinframe->qgeneratebase = false;
3756                 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);
3757                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
3758                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
3759         }
3760         else
3761         {
3762                 skinframe->qgeneratemerged = false;
3763                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3764         }
3765
3766         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3767         {
3768                 Mem_Free(skinframe->qpixels);
3769                 skinframe->qpixels = NULL;
3770         }
3771 }
3772
3773 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)
3774 {
3775         int i;
3776         skinframe_t *skinframe;
3777
3778         if (cls.state == ca_dedicated)
3779                 return NULL;
3780
3781         // if already loaded just return it, otherwise make a new skinframe
3782         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3783         if (skinframe && skinframe->base)
3784                 return skinframe;
3785
3786         skinframe->stain = NULL;
3787         skinframe->merged = NULL;
3788         skinframe->base = r_texture_notexture;
3789         skinframe->pants = NULL;
3790         skinframe->shirt = NULL;
3791         skinframe->nmap = r_texture_blanknormalmap;
3792         skinframe->gloss = NULL;
3793         skinframe->glow = NULL;
3794         skinframe->fog = NULL;
3795         skinframe->hasalpha = false;
3796
3797         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3798         if (!skindata)
3799                 return NULL;
3800
3801         if (developer_loading.integer)
3802                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3803
3804         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3805         if (textureflags & TEXF_ALPHA)
3806         {
3807                 for (i = 0;i < width * height;i++)
3808                 {
3809                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3810                         {
3811                                 skinframe->hasalpha = true;
3812                                 break;
3813                         }
3814                 }
3815                 if (r_loadfog && skinframe->hasalpha)
3816                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3817         }
3818
3819         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3820         //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]);
3821
3822         return skinframe;
3823 }
3824
3825 skinframe_t *R_SkinFrame_LoadMissing(void)
3826 {
3827         skinframe_t *skinframe;
3828
3829         if (cls.state == ca_dedicated)
3830                 return NULL;
3831
3832         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3833         skinframe->stain = NULL;
3834         skinframe->merged = NULL;
3835         skinframe->base = r_texture_notexture;
3836         skinframe->pants = NULL;
3837         skinframe->shirt = NULL;
3838         skinframe->nmap = r_texture_blanknormalmap;
3839         skinframe->gloss = NULL;
3840         skinframe->glow = NULL;
3841         skinframe->fog = NULL;
3842         skinframe->hasalpha = false;
3843
3844         skinframe->avgcolor[0] = rand() / RAND_MAX;
3845         skinframe->avgcolor[1] = rand() / RAND_MAX;
3846         skinframe->avgcolor[2] = rand() / RAND_MAX;
3847         skinframe->avgcolor[3] = 1;
3848
3849         return skinframe;
3850 }
3851
3852 void R_Main_FreeViewCache(void)
3853 {
3854         if (r_refdef.viewcache.entityvisible)
3855                 Mem_Free(r_refdef.viewcache.entityvisible);
3856         if (r_refdef.viewcache.world_pvsbits)
3857                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3858         if (r_refdef.viewcache.world_leafvisible)
3859                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3860         if (r_refdef.viewcache.world_surfacevisible)
3861                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3862         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3863 }
3864
3865 void R_Main_ResizeViewCache(void)
3866 {
3867         int numentities = r_refdef.scene.numentities;
3868         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3869         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3870         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3871         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3872         if (r_refdef.viewcache.maxentities < numentities)
3873         {
3874                 r_refdef.viewcache.maxentities = numentities;
3875                 if (r_refdef.viewcache.entityvisible)
3876                         Mem_Free(r_refdef.viewcache.entityvisible);
3877                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3878         }
3879         if (r_refdef.viewcache.world_numclusters != numclusters)
3880         {
3881                 r_refdef.viewcache.world_numclusters = numclusters;
3882                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3883                 if (r_refdef.viewcache.world_pvsbits)
3884                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3885                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3886         }
3887         if (r_refdef.viewcache.world_numleafs != numleafs)
3888         {
3889                 r_refdef.viewcache.world_numleafs = numleafs;
3890                 if (r_refdef.viewcache.world_leafvisible)
3891                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3892                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3893         }
3894         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3895         {
3896                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3897                 if (r_refdef.viewcache.world_surfacevisible)
3898                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3899                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3900         }
3901 }
3902
3903 extern rtexture_t *loadingscreentexture;
3904 void gl_main_start(void)
3905 {
3906         loadingscreentexture = NULL;
3907         r_texture_blanknormalmap = NULL;
3908         r_texture_white = NULL;
3909         r_texture_grey128 = NULL;
3910         r_texture_black = NULL;
3911         r_texture_whitecube = NULL;
3912         r_texture_normalizationcube = NULL;
3913         r_texture_fogattenuation = NULL;
3914         r_texture_gammaramps = NULL;
3915
3916         switch(vid.renderpath)
3917         {
3918         case RENDERPATH_GL20:
3919         case RENDERPATH_CGGL:
3920                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3921                 Cvar_SetValueQuick(&gl_combine, 1);
3922                 Cvar_SetValueQuick(&r_glsl, 1);
3923                 r_loadnormalmap = true;
3924                 r_loadgloss = true;
3925                 r_loadfog = false;
3926                 break;
3927         case RENDERPATH_GL13:
3928                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3929                 Cvar_SetValueQuick(&gl_combine, 1);
3930                 Cvar_SetValueQuick(&r_glsl, 0);
3931                 r_loadnormalmap = false;
3932                 r_loadgloss = false;
3933                 r_loadfog = true;
3934                 break;
3935         case RENDERPATH_GL11:
3936                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3937                 Cvar_SetValueQuick(&gl_combine, 0);
3938                 Cvar_SetValueQuick(&r_glsl, 0);
3939                 r_loadnormalmap = false;
3940                 r_loadgloss = false;
3941                 r_loadfog = true;
3942                 break;
3943         }
3944
3945         R_AnimCache_Free();
3946         R_FrameData_Reset();
3947
3948         r_numqueries = 0;
3949         r_maxqueries = 0;
3950         memset(r_queries, 0, sizeof(r_queries));
3951
3952         r_qwskincache = NULL;
3953         r_qwskincache_size = 0;
3954
3955         // set up r_skinframe loading system for textures
3956         memset(&r_skinframe, 0, sizeof(r_skinframe));
3957         r_skinframe.loadsequence = 1;
3958         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3959
3960         r_main_texturepool = R_AllocTexturePool();
3961         R_BuildBlankTextures();
3962         R_BuildNoTexture();
3963         if (vid.support.arb_texture_cube_map)
3964         {
3965                 R_BuildWhiteCube();
3966                 R_BuildNormalizationCube();
3967         }
3968         r_texture_fogattenuation = NULL;
3969         r_texture_gammaramps = NULL;
3970         //r_texture_fogintensity = NULL;
3971         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3972         memset(&r_waterstate, 0, sizeof(r_waterstate));
3973         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3974         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3975 #ifdef SUPPORTCG
3976         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
3977         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
3978 #endif
3979         memset(&r_svbsp, 0, sizeof (r_svbsp));
3980
3981         r_refdef.fogmasktable_density = 0;
3982 }
3983
3984 void gl_main_shutdown(void)
3985 {
3986         R_AnimCache_Free();
3987         R_FrameData_Reset();
3988
3989         R_Main_FreeViewCache();
3990
3991         if (r_maxqueries)
3992                 qglDeleteQueriesARB(r_maxqueries, r_queries);
3993
3994         r_numqueries = 0;
3995         r_maxqueries = 0;
3996         memset(r_queries, 0, sizeof(r_queries));
3997
3998         r_qwskincache = NULL;
3999         r_qwskincache_size = 0;
4000
4001         // clear out the r_skinframe state
4002         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4003         memset(&r_skinframe, 0, sizeof(r_skinframe));
4004
4005         if (r_svbsp.nodes)
4006                 Mem_Free(r_svbsp.nodes);
4007         memset(&r_svbsp, 0, sizeof (r_svbsp));
4008         R_FreeTexturePool(&r_main_texturepool);
4009         loadingscreentexture = NULL;
4010         r_texture_blanknormalmap = NULL;
4011         r_texture_white = NULL;
4012         r_texture_grey128 = NULL;
4013         r_texture_black = NULL;
4014         r_texture_whitecube = NULL;
4015         r_texture_normalizationcube = NULL;
4016         r_texture_fogattenuation = NULL;
4017         r_texture_gammaramps = NULL;
4018         //r_texture_fogintensity = NULL;
4019         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4020         memset(&r_waterstate, 0, sizeof(r_waterstate));
4021         R_GLSL_Restart_f();
4022 }
4023
4024 extern void CL_ParseEntityLump(char *entitystring);
4025 void gl_main_newmap(void)
4026 {
4027         // FIXME: move this code to client
4028         int l;
4029         char *entities, entname[MAX_QPATH];
4030         if (r_qwskincache)
4031                 Mem_Free(r_qwskincache);
4032         r_qwskincache = NULL;
4033         r_qwskincache_size = 0;
4034         if (cl.worldmodel)
4035         {
4036                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
4037                 l = (int)strlen(entname) - 4;
4038                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
4039                 {
4040                         memcpy(entname + l, ".ent", 5);
4041                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4042                         {
4043                                 CL_ParseEntityLump(entities);
4044                                 Mem_Free(entities);
4045                                 return;
4046                         }
4047                 }
4048                 if (cl.worldmodel->brush.entities)
4049                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4050         }
4051         R_Main_FreeViewCache();
4052
4053         R_FrameData_Reset();
4054 }
4055
4056 void GL_Main_Init(void)
4057 {
4058         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4059
4060         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4061         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4062         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4063         if (gamemode == GAME_NEHAHRA)
4064         {
4065                 Cvar_RegisterVariable (&gl_fogenable);
4066                 Cvar_RegisterVariable (&gl_fogdensity);
4067                 Cvar_RegisterVariable (&gl_fogred);
4068                 Cvar_RegisterVariable (&gl_foggreen);
4069                 Cvar_RegisterVariable (&gl_fogblue);
4070                 Cvar_RegisterVariable (&gl_fogstart);
4071                 Cvar_RegisterVariable (&gl_fogend);
4072                 Cvar_RegisterVariable (&gl_skyclip);
4073         }
4074         Cvar_RegisterVariable(&r_motionblur);
4075         Cvar_RegisterVariable(&r_motionblur_maxblur);
4076         Cvar_RegisterVariable(&r_motionblur_bmin);
4077         Cvar_RegisterVariable(&r_motionblur_vmin);
4078         Cvar_RegisterVariable(&r_motionblur_vmax);
4079         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4080         Cvar_RegisterVariable(&r_motionblur_randomize);
4081         Cvar_RegisterVariable(&r_damageblur);
4082         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4083         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4084         Cvar_RegisterVariable(&r_equalize_entities_by);
4085         Cvar_RegisterVariable(&r_equalize_entities_to);
4086         Cvar_RegisterVariable(&r_depthfirst);
4087         Cvar_RegisterVariable(&r_useinfinitefarclip);
4088         Cvar_RegisterVariable(&r_farclip_base);
4089         Cvar_RegisterVariable(&r_farclip_world);
4090         Cvar_RegisterVariable(&r_nearclip);
4091         Cvar_RegisterVariable(&r_showbboxes);
4092         Cvar_RegisterVariable(&r_showsurfaces);
4093         Cvar_RegisterVariable(&r_showtris);
4094         Cvar_RegisterVariable(&r_shownormals);
4095         Cvar_RegisterVariable(&r_showlighting);
4096         Cvar_RegisterVariable(&r_showshadowvolumes);
4097         Cvar_RegisterVariable(&r_showcollisionbrushes);
4098         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4099         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4100         Cvar_RegisterVariable(&r_showdisabledepthtest);
4101         Cvar_RegisterVariable(&r_drawportals);
4102         Cvar_RegisterVariable(&r_drawentities);
4103         Cvar_RegisterVariable(&r_cullentities_trace);
4104         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4105         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4106         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4107         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4108         Cvar_RegisterVariable(&r_drawviewmodel);
4109         Cvar_RegisterVariable(&r_speeds);
4110         Cvar_RegisterVariable(&r_fullbrights);
4111         Cvar_RegisterVariable(&r_wateralpha);
4112         Cvar_RegisterVariable(&r_dynamic);
4113         Cvar_RegisterVariable(&r_fullbright);
4114         Cvar_RegisterVariable(&r_shadows);
4115         Cvar_RegisterVariable(&r_shadows_darken);
4116         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4117         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4118         Cvar_RegisterVariable(&r_shadows_throwdistance);
4119         Cvar_RegisterVariable(&r_shadows_throwdirection);
4120         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4121         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4122         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4123         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4124         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4125         Cvar_RegisterVariable(&r_fog_exp2);
4126         Cvar_RegisterVariable(&r_drawfog);
4127         Cvar_RegisterVariable(&r_transparentdepthmasking);
4128         Cvar_RegisterVariable(&r_textureunits);
4129         Cvar_RegisterVariable(&gl_combine);
4130         Cvar_RegisterVariable(&r_glsl);
4131         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4132         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4133         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4134         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4135         Cvar_RegisterVariable(&r_glsl_postprocess);
4136         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4137         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4138         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4139         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4140         Cvar_RegisterVariable(&r_water);
4141         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4142         Cvar_RegisterVariable(&r_water_clippingplanebias);
4143         Cvar_RegisterVariable(&r_water_refractdistort);
4144         Cvar_RegisterVariable(&r_water_reflectdistort);
4145         Cvar_RegisterVariable(&r_lerpsprites);
4146         Cvar_RegisterVariable(&r_lerpmodels);
4147         Cvar_RegisterVariable(&r_lerplightstyles);
4148         Cvar_RegisterVariable(&r_waterscroll);
4149         Cvar_RegisterVariable(&r_bloom);
4150         Cvar_RegisterVariable(&r_bloom_colorscale);
4151         Cvar_RegisterVariable(&r_bloom_brighten);
4152         Cvar_RegisterVariable(&r_bloom_blur);
4153         Cvar_RegisterVariable(&r_bloom_resolution);
4154         Cvar_RegisterVariable(&r_bloom_colorexponent);
4155         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4156         Cvar_RegisterVariable(&r_hdr);
4157         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4158         Cvar_RegisterVariable(&r_hdr_glowintensity);
4159         Cvar_RegisterVariable(&r_hdr_range);
4160         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4161         Cvar_RegisterVariable(&developer_texturelogging);
4162         Cvar_RegisterVariable(&gl_lightmaps);
4163         Cvar_RegisterVariable(&r_test);
4164         Cvar_RegisterVariable(&r_batchmode);
4165         Cvar_RegisterVariable(&r_glsl_saturation);
4166         Cvar_RegisterVariable(&r_framedatasize);
4167         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4168                 Cvar_SetValue("r_fullbrights", 0);
4169         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
4170
4171         Cvar_RegisterVariable(&r_track_sprites);
4172         Cvar_RegisterVariable(&r_track_sprites_flags);
4173         Cvar_RegisterVariable(&r_track_sprites_scalew);
4174         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4175 }
4176
4177 extern void R_Textures_Init(void);
4178 extern void GL_Draw_Init(void);
4179 extern void GL_Main_Init(void);
4180 extern void R_Shadow_Init(void);
4181 extern void R_Sky_Init(void);
4182 extern void GL_Surf_Init(void);
4183 extern void R_Particles_Init(void);
4184 extern void R_Explosion_Init(void);
4185 extern void gl_backend_init(void);
4186 extern void Sbar_Init(void);
4187 extern void R_LightningBeams_Init(void);
4188 extern void Mod_RenderInit(void);
4189 extern void Font_Init(void);
4190
4191 void Render_Init(void)
4192 {
4193         gl_backend_init();
4194         R_Textures_Init();
4195         GL_Main_Init();
4196         Font_Init();
4197         GL_Draw_Init();
4198         R_Shadow_Init();
4199         R_Sky_Init();
4200         GL_Surf_Init();
4201         Sbar_Init();
4202         R_Particles_Init();
4203         R_Explosion_Init();
4204         R_LightningBeams_Init();
4205         Mod_RenderInit();
4206 }
4207
4208 /*
4209 ===============
4210 GL_Init
4211 ===============
4212 */
4213 extern char *ENGINE_EXTENSIONS;
4214 void GL_Init (void)
4215 {
4216         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4217         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4218         gl_version = (const char *)qglGetString(GL_VERSION);
4219         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4220
4221         if (!gl_extensions)
4222                 gl_extensions = "";
4223         if (!gl_platformextensions)
4224                 gl_platformextensions = "";
4225
4226         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4227         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4228         Con_Printf("GL_VERSION: %s\n", gl_version);
4229         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4230         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4231
4232         VID_CheckExtensions();
4233
4234         // LordHavoc: report supported extensions
4235         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4236
4237         // clear to black (loading plaque will be seen over this)
4238         CHECKGLERROR
4239         qglClearColor(0,0,0,1);CHECKGLERROR
4240         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
4241 }
4242
4243 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4244 {
4245         int i;
4246         mplane_t *p;
4247         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4248         {
4249                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4250                 if (i == 4)
4251                         continue;
4252                 p = r_refdef.view.frustum + i;
4253                 switch(p->signbits)
4254                 {
4255                 default:
4256                 case 0:
4257                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4258                                 return true;
4259                         break;
4260                 case 1:
4261                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4262                                 return true;
4263                         break;
4264                 case 2:
4265                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4266                                 return true;
4267                         break;
4268                 case 3:
4269                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4270                                 return true;
4271                         break;
4272                 case 4:
4273                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4274                                 return true;
4275                         break;
4276                 case 5:
4277                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4278                                 return true;
4279                         break;
4280                 case 6:
4281                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4282                                 return true;
4283                         break;
4284                 case 7:
4285                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4286                                 return true;
4287                         break;
4288                 }
4289         }
4290         return false;
4291 }
4292
4293 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4294 {
4295         int i;
4296         const mplane_t *p;
4297         for (i = 0;i < numplanes;i++)
4298         {
4299                 p = planes + i;
4300                 switch(p->signbits)
4301                 {
4302                 default:
4303                 case 0:
4304                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4305                                 return true;
4306                         break;
4307                 case 1:
4308                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4309                                 return true;
4310                         break;
4311                 case 2:
4312                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4313                                 return true;
4314                         break;
4315                 case 3:
4316                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4317                                 return true;
4318                         break;
4319                 case 4:
4320                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4321                                 return true;
4322                         break;
4323                 case 5:
4324                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4325                                 return true;
4326                         break;
4327                 case 6:
4328                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4329                                 return true;
4330                         break;
4331                 case 7:
4332                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4333                                 return true;
4334                         break;
4335                 }
4336         }
4337         return false;
4338 }
4339
4340 //==================================================================================
4341
4342 // LordHavoc: this stores temporary data used within the same frame
4343
4344 qboolean r_framedata_failed;
4345 static size_t r_framedata_size;
4346 static size_t r_framedata_current;
4347 static void *r_framedata_base;
4348
4349 void R_FrameData_Reset(void)
4350 {
4351         if (r_framedata_base);
4352                 Mem_Free(r_framedata_base);
4353         r_framedata_base = NULL;
4354         r_framedata_size = 0;
4355         r_framedata_current = 0;
4356         r_framedata_failed = false;
4357 }
4358
4359 void R_FrameData_NewFrame(void)
4360 {
4361         size_t wantedsize;
4362         if (r_framedata_failed)
4363                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
4364         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4365         wantedsize = bound(65536, wantedsize, 128*1024*1024);
4366         if (r_framedata_size != wantedsize)
4367         {
4368                 r_framedata_size = wantedsize;
4369                 if (r_framedata_base);
4370                         Mem_Free(r_framedata_base);
4371                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
4372         }
4373         r_framedata_current = 0;
4374         r_framedata_failed = false;
4375 }
4376
4377 void *R_FrameData_Alloc(size_t size)
4378 {
4379         void *data;
4380
4381         // align to 16 byte boundary
4382         size = (size + 15) & ~15;
4383         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
4384         r_framedata_current += size;
4385
4386         // check overflow
4387         if (r_framedata_current > r_framedata_size)
4388                 r_framedata_failed = true;
4389
4390         // return NULL on everything after a failure
4391         if (r_framedata_failed)
4392                 return NULL;
4393
4394         return data;
4395 }
4396
4397 void *R_FrameData_Store(size_t size, void *data)
4398 {
4399         void *d = R_FrameData_Alloc(size);
4400         if (d)
4401                 memcpy(d, data, size);
4402         return d;
4403 }
4404
4405 //==================================================================================
4406
4407 // LordHavoc: animcache originally written by Echon, rewritten since then
4408
4409 /**
4410  * Animation cache prevents re-generating mesh data for an animated model
4411  * multiple times in one frame for lighting, shadowing, reflections, etc.
4412  */
4413
4414 void R_AnimCache_Free(void)
4415 {
4416 }
4417
4418 void R_AnimCache_ClearCache(void)
4419 {
4420         int i;
4421         entity_render_t *ent;
4422
4423         for (i = 0;i < r_refdef.scene.numentities;i++)
4424         {
4425                 ent = r_refdef.scene.entities[i];
4426                 ent->animcache_vertex3f = NULL;
4427                 ent->animcache_normal3f = NULL;
4428                 ent->animcache_svector3f = NULL;
4429                 ent->animcache_tvector3f = NULL;
4430         }
4431 }
4432
4433 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4434 {
4435         dp_model_t *model = ent->model;
4436         int numvertices;
4437         // see if it's already cached this frame
4438         if (ent->animcache_vertex3f)
4439         {
4440                 // add normals/tangents if needed
4441                 if (wantnormals || wanttangents)
4442                 {
4443                         if (ent->animcache_normal3f)
4444                                 wantnormals = false;
4445                         if (ent->animcache_svector3f)
4446                                 wanttangents = false;
4447                         if (wantnormals || wanttangents)
4448                         {
4449                                 numvertices = model->surfmesh.num_vertices;
4450                                 if (wantnormals)
4451                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4452                                 if (wanttangents)
4453                                 {
4454                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4455                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4456                                 }
4457                                 if (!r_framedata_failed)
4458                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4459                         }
4460                 }
4461         }
4462         else
4463         {
4464                 // see if this ent is worth caching
4465                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4466                         return false;
4467                 // get some memory for this entity and generate mesh data
4468                 numvertices = model->surfmesh.num_vertices;
4469                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4470                 if (wantnormals)
4471                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4472                 if (wanttangents)
4473                 {
4474                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4475                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4476                 }
4477                 if (!r_framedata_failed)
4478                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4479         }
4480         return !r_framedata_failed;
4481 }
4482
4483 void R_AnimCache_CacheVisibleEntities(void)
4484 {
4485         int i;
4486         qboolean wantnormals = !r_showsurfaces.integer;
4487         qboolean wanttangents = !r_showsurfaces.integer;
4488
4489         switch(vid.renderpath)
4490         {
4491         case RENDERPATH_GL20:
4492         case RENDERPATH_CGGL:
4493                 break;
4494         case RENDERPATH_GL13:
4495         case RENDERPATH_GL11:
4496                 wanttangents = false;
4497                 break;
4498         }
4499
4500         // TODO: thread this
4501         // NOTE: R_PrepareRTLights() also caches entities
4502
4503         for (i = 0;i < r_refdef.scene.numentities;i++)
4504                 if (r_refdef.viewcache.entityvisible[i])
4505                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4506
4507         if (r_shadows.integer)
4508                 for (i = 0;i < r_refdef.scene.numentities;i++)
4509                         if (!r_refdef.viewcache.entityvisible[i])
4510                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
4511 }
4512
4513 //==================================================================================
4514
4515 static void R_View_UpdateEntityLighting (void)
4516 {
4517         int i;
4518         entity_render_t *ent;
4519         vec3_t tempdiffusenormal, avg;
4520         vec_t f, fa, fd, fdd;
4521
4522         for (i = 0;i < r_refdef.scene.numentities;i++)
4523         {
4524                 ent = r_refdef.scene.entities[i];
4525
4526                 // skip unseen models
4527                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
4528                         continue;
4529
4530                 // skip bsp models
4531                 if (ent->model && ent->model->brush.num_leafs)
4532                 {
4533                         // TODO: use modellight for r_ambient settings on world?
4534                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4535                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4536                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4537                         continue;
4538                 }
4539
4540                 // fetch the lighting from the worldmodel data
4541                 VectorClear(ent->modellight_ambient);
4542                 VectorClear(ent->modellight_diffuse);
4543                 VectorClear(tempdiffusenormal);
4544                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4545                 {
4546                         vec3_t org;
4547                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4548                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
4549                         if(ent->flags & RENDER_EQUALIZE)
4550                         {
4551                                 // first fix up ambient lighting...
4552                                 if(r_equalize_entities_minambient.value > 0)
4553                                 {
4554                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4555                                         if(fd > 0)
4556                                         {
4557                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4558                                                 if(fa < r_equalize_entities_minambient.value * fd)
4559                                                 {
4560                                                         // solve:
4561                                                         //   fa'/fd' = minambient
4562                                                         //   fa'+0.25*fd' = fa+0.25*fd
4563                                                         //   ...
4564                                                         //   fa' = fd' * minambient
4565                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4566                                                         //   ...
4567                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4568                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4569                                                         //   ...
4570                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4571                                                         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
4572                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4573                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4574                                                 }
4575                                         }
4576                                 }
4577
4578                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4579                                 {
4580                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
4581                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
4582                                         if(f > 0)
4583                                         {
4584                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
4585                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
4586                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4587                                         }
4588                                 }
4589                         }
4590                 }
4591                 else // highly rare
4592                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4593
4594                 // move the light direction into modelspace coordinates for lighting code
4595                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4596                 if(VectorLength2(ent->modellight_lightdir) == 0)
4597                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4598                 VectorNormalize(ent->modellight_lightdir);
4599         }
4600 }
4601
4602 #define MAX_LINEOFSIGHTTRACES 64
4603
4604 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4605 {
4606         int i;
4607         vec3_t boxmins, boxmaxs;
4608         vec3_t start;
4609         vec3_t end;
4610         dp_model_t *model = r_refdef.scene.worldmodel;
4611
4612         if (!model || !model->brush.TraceLineOfSight)
4613                 return true;
4614
4615         // expand the box a little
4616         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4617         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4618         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4619         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4620         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4621         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4622
4623         // try center
4624         VectorCopy(eye, start);
4625         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4626         if (model->brush.TraceLineOfSight(model, start, end))
4627                 return true;
4628
4629         // try various random positions
4630         for (i = 0;i < numsamples;i++)
4631         {
4632                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4633                 if (model->brush.TraceLineOfSight(model, start, end))
4634                         return true;
4635         }
4636
4637         return false;
4638 }
4639
4640
4641 static void R_View_UpdateEntityVisible (void)
4642 {
4643         int i;
4644         int renderimask;
4645         int samples;
4646         entity_render_t *ent;
4647
4648         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
4649         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4650         {
4651                 // worldmodel can check visibility
4652                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4653                 for (i = 0;i < r_refdef.scene.numentities;i++)
4654                 {
4655                         ent = r_refdef.scene.entities[i];
4656                         if (!(ent->flags & renderimask))
4657                         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)))
4658                         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))
4659                                 r_refdef.viewcache.entityvisible[i] = true;
4660                 }
4661                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
4662                 {
4663                         for (i = 0;i < r_refdef.scene.numentities;i++)
4664                         {
4665                                 ent = r_refdef.scene.entities[i];
4666                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4667                                 {
4668                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4669                                         if (samples < 0)
4670                                                 continue; // temp entities do pvs only
4671                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4672                                                 ent->last_trace_visibility = realtime;
4673                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4674                                                 r_refdef.viewcache.entityvisible[i] = 0;
4675                                 }
4676                         }
4677                 }
4678         }
4679         else
4680         {
4681                 // no worldmodel or it can't check visibility
4682                 for (i = 0;i < r_refdef.scene.numentities;i++)
4683                 {
4684                         ent = r_refdef.scene.entities[i];
4685                         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));
4686                 }
4687         }
4688 }
4689
4690 /// only used if skyrendermasked, and normally returns false
4691 int R_DrawBrushModelsSky (void)
4692 {
4693         int i, sky;
4694         entity_render_t *ent;
4695
4696         sky = false;
4697         for (i = 0;i < r_refdef.scene.numentities;i++)
4698         {
4699                 if (!r_refdef.viewcache.entityvisible[i])
4700                         continue;
4701                 ent = r_refdef.scene.entities[i];
4702                 if (!ent->model || !ent->model->DrawSky)
4703                         continue;
4704                 ent->model->DrawSky(ent);
4705                 sky = true;
4706         }
4707         return sky;
4708 }
4709
4710 static void R_DrawNoModel(entity_render_t *ent);
4711 static void R_DrawModels(void)
4712 {
4713         int i;
4714         entity_render_t *ent;
4715
4716         for (i = 0;i < r_refdef.scene.numentities;i++)
4717         {
4718                 if (!r_refdef.viewcache.entityvisible[i])
4719                         continue;
4720                 ent = r_refdef.scene.entities[i];
4721                 r_refdef.stats.entities++;
4722                 if (ent->model && ent->model->Draw != NULL)
4723                         ent->model->Draw(ent);
4724                 else
4725                         R_DrawNoModel(ent);
4726         }
4727 }
4728
4729 static void R_DrawModelsDepth(void)
4730 {
4731         int i;
4732         entity_render_t *ent;
4733
4734         for (i = 0;i < r_refdef.scene.numentities;i++)
4735         {
4736                 if (!r_refdef.viewcache.entityvisible[i])
4737                         continue;
4738                 ent = r_refdef.scene.entities[i];
4739                 if (ent->model && ent->model->DrawDepth != NULL)
4740                         ent->model->DrawDepth(ent);
4741         }
4742 }
4743
4744 static void R_DrawModelsDebug(void)
4745 {
4746         int i;
4747         entity_render_t *ent;
4748
4749         for (i = 0;i < r_refdef.scene.numentities;i++)
4750         {
4751                 if (!r_refdef.viewcache.entityvisible[i])
4752                         continue;
4753                 ent = r_refdef.scene.entities[i];
4754                 if (ent->model && ent->model->DrawDebug != NULL)
4755                         ent->model->DrawDebug(ent);
4756         }
4757 }
4758
4759 static void R_DrawModelsAddWaterPlanes(void)
4760 {
4761         int i;
4762         entity_render_t *ent;
4763
4764         for (i = 0;i < r_refdef.scene.numentities;i++)
4765         {
4766                 if (!r_refdef.viewcache.entityvisible[i])
4767                         continue;
4768                 ent = r_refdef.scene.entities[i];
4769                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4770                         ent->model->DrawAddWaterPlanes(ent);
4771         }
4772 }
4773
4774 static void R_View_SetFrustum(void)
4775 {
4776         int i;
4777         double slopex, slopey;
4778         vec3_t forward, left, up, origin;
4779
4780         // we can't trust r_refdef.view.forward and friends in reflected scenes
4781         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4782
4783 #if 0
4784         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4785         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4786         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4787         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4788         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4789         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4790         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4791         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4792         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4793         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4794         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4795         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4796 #endif
4797
4798 #if 0
4799         zNear = r_refdef.nearclip;
4800         nudge = 1.0 - 1.0 / (1<<23);
4801         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4802         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4803         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4804         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4805         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4806         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4807         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4808         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4809 #endif
4810
4811
4812
4813 #if 0
4814         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4815         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4816         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4817         r_refdef.view.frustum[0].dist = m[15] - m[12];
4818
4819         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4820         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4821         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4822         r_refdef.view.frustum[1].dist = m[15] + m[12];
4823
4824         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4825         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4826         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4827         r_refdef.view.frustum[2].dist = m[15] - m[13];
4828
4829         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4830         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4831         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4832         r_refdef.view.frustum[3].dist = m[15] + m[13];
4833
4834         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4835         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4836         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4837         r_refdef.view.frustum[4].dist = m[15] - m[14];
4838
4839         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4840         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4841         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4842         r_refdef.view.frustum[5].dist = m[15] + m[14];
4843 #endif
4844
4845         if (r_refdef.view.useperspective)
4846         {
4847                 slopex = 1.0 / r_refdef.view.frustum_x;
4848                 slopey = 1.0 / r_refdef.view.frustum_y;
4849                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4850                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
4851                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
4852                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
4853                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4854
4855                 // Leaving those out was a mistake, those were in the old code, and they
4856                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4857                 // I couldn't reproduce it after adding those normalizations. --blub
4858                 VectorNormalize(r_refdef.view.frustum[0].normal);
4859                 VectorNormalize(r_refdef.view.frustum[1].normal);
4860                 VectorNormalize(r_refdef.view.frustum[2].normal);
4861                 VectorNormalize(r_refdef.view.frustum[3].normal);
4862
4863                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4864                 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]);
4865                 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]);
4866                 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]);
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[3]);
4868
4869                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4870                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4871                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4872                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4873                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4874         }
4875         else
4876         {
4877                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4878                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4879                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4880                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4881                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4882                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4883                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4884                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4885                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4886                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4887         }
4888         r_refdef.view.numfrustumplanes = 5;
4889
4890         if (r_refdef.view.useclipplane)
4891         {
4892                 r_refdef.view.numfrustumplanes = 6;
4893                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4894         }
4895
4896         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4897                 PlaneClassify(r_refdef.view.frustum + i);
4898
4899         // LordHavoc: note to all quake engine coders, Quake had a special case
4900         // for 90 degrees which assumed a square view (wrong), so I removed it,
4901         // Quake2 has it disabled as well.
4902
4903         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4904         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4905         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4906         //PlaneClassify(&frustum[0]);
4907
4908         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4909         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4910         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4911         //PlaneClassify(&frustum[1]);
4912
4913         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4914         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4915         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4916         //PlaneClassify(&frustum[2]);
4917
4918         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4919         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4920         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4921         //PlaneClassify(&frustum[3]);
4922
4923         // nearclip plane
4924         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4925         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4926         //PlaneClassify(&frustum[4]);
4927 }
4928
4929 void R_View_Update(void)
4930 {
4931         R_Main_ResizeViewCache();
4932         R_View_SetFrustum();
4933         R_View_WorldVisibility(r_refdef.view.useclipplane);
4934         R_View_UpdateEntityVisible();
4935         R_View_UpdateEntityLighting();
4936 }
4937
4938 void R_SetupView(qboolean allowwaterclippingplane)
4939 {
4940         const float *customclipplane = NULL;
4941         float plane[4];
4942         if (r_refdef.view.useclipplane && allowwaterclippingplane)
4943         {
4944                 // LordHavoc: couldn't figure out how to make this approach the
4945                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4946                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4947                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4948                         dist = r_refdef.view.clipplane.dist;
4949                 plane[0] = r_refdef.view.clipplane.normal[0];
4950                 plane[1] = r_refdef.view.clipplane.normal[1];
4951                 plane[2] = r_refdef.view.clipplane.normal[2];
4952                 plane[3] = dist;
4953                 customclipplane = plane;
4954         }
4955
4956         if (!r_refdef.view.useperspective)
4957                 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);
4958         else if (vid.stencil && r_useinfinitefarclip.integer)
4959                 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);
4960         else
4961                 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);
4962         R_SetViewport(&r_refdef.view.viewport);
4963 }
4964
4965 void R_EntityMatrix(const matrix4x4_t *matrix)
4966 {
4967         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
4968         {
4969                 gl_modelmatrixchanged = false;
4970                 gl_modelmatrix = *matrix;
4971                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
4972                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
4973                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
4974                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
4975                 CHECKGLERROR
4976                 switch(vid.renderpath)
4977                 {
4978                 case RENDERPATH_GL20:
4979                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4980                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4981                         break;
4982                 case RENDERPATH_CGGL:
4983                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix >= 0) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4984                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4985                         break;
4986                 case RENDERPATH_GL13:
4987                 case RENDERPATH_GL11:
4988                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4989                         break;
4990                 }
4991         }
4992 }
4993
4994 void R_ResetViewRendering2D(void)
4995 {
4996         r_viewport_t viewport;
4997         DrawQ_Finish();
4998
4999         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5000         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);
5001         R_SetViewport(&viewport);
5002         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5003         GL_Color(1, 1, 1, 1);
5004         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5005         GL_BlendFunc(GL_ONE, GL_ZERO);
5006         GL_AlphaTest(false);
5007         GL_ScissorTest(false);
5008         GL_DepthMask(false);
5009         GL_DepthRange(0, 1);
5010         GL_DepthTest(false);
5011         R_EntityMatrix(&identitymatrix);
5012         R_Mesh_ResetTextureState();
5013         GL_PolygonOffset(0, 0);
5014         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5015         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5016         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
5017         qglStencilMask(~0);CHECKGLERROR
5018         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
5019         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
5020         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
5021 }
5022
5023 void R_ResetViewRendering3D(void)
5024 {
5025         DrawQ_Finish();
5026
5027         R_SetupView(true);
5028         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5029         GL_Color(1, 1, 1, 1);
5030         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5031         GL_BlendFunc(GL_ONE, GL_ZERO);
5032         GL_AlphaTest(false);
5033         GL_ScissorTest(true);
5034         GL_DepthMask(true);
5035         GL_DepthRange(0, 1);
5036         GL_DepthTest(true);
5037         R_EntityMatrix(&identitymatrix);
5038         R_Mesh_ResetTextureState();
5039         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5040         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5041         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5042         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
5043         qglStencilMask(~0);CHECKGLERROR
5044         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
5045         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
5046         GL_CullFace(r_refdef.view.cullface_back);
5047 }
5048
5049 void R_RenderScene(void);
5050 void R_RenderWaterPlanes(void);
5051
5052 static void R_Water_StartFrame(void)
5053 {
5054         int i;
5055         int waterwidth, waterheight, texturewidth, textureheight;
5056         r_waterstate_waterplane_t *p;
5057
5058         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5059                 return;
5060
5061         switch(vid.renderpath)
5062         {
5063         case RENDERPATH_GL20:
5064         case RENDERPATH_CGGL:
5065                 break;
5066         case RENDERPATH_GL13:
5067         case RENDERPATH_GL11:
5068                 return;
5069         }
5070
5071         // set waterwidth and waterheight to the water resolution that will be
5072         // used (often less than the screen resolution for faster rendering)
5073         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5074         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5075
5076         // calculate desired texture sizes
5077         // can't use water if the card does not support the texture size
5078         if (!r_water.integer || r_showsurfaces.integer)
5079                 texturewidth = textureheight = waterwidth = waterheight = 0;
5080         else if (vid.support.arb_texture_non_power_of_two)
5081         {
5082                 texturewidth = waterwidth;
5083                 textureheight = waterheight;
5084         }
5085         else
5086         {
5087                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5088                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5089         }
5090
5091         // allocate textures as needed
5092         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
5093         {
5094                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5095                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5096                 {
5097                         if (p->texture_refraction)
5098                                 R_FreeTexture(p->texture_refraction);
5099                         p->texture_refraction = NULL;
5100                         if (p->texture_reflection)
5101                                 R_FreeTexture(p->texture_reflection);
5102                         p->texture_reflection = NULL;
5103                 }
5104                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5105                 r_waterstate.texturewidth = texturewidth;
5106                 r_waterstate.textureheight = textureheight;
5107         }
5108
5109         if (r_waterstate.texturewidth)
5110         {
5111                 r_waterstate.enabled = true;
5112
5113                 // when doing a reduced render (HDR) we want to use a smaller area
5114                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5115                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5116
5117                 // set up variables that will be used in shader setup
5118                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5119                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5120                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5121                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5122         }
5123
5124         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5125         r_waterstate.numwaterplanes = 0;
5126 }
5127
5128 void R_Water_AddWaterPlane(msurface_t *surface)
5129 {
5130         int triangleindex, planeindex;
5131         const int *e;
5132         vec3_t vert[3];
5133         vec3_t normal;
5134         vec3_t center;
5135         mplane_t plane;
5136         r_waterstate_waterplane_t *p;
5137         texture_t *t = R_GetCurrentTexture(surface->texture);
5138         // just use the first triangle with a valid normal for any decisions
5139         VectorClear(normal);
5140         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5141         {
5142                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5143                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5144                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5145                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5146                 if (VectorLength2(normal) >= 0.001)
5147                         break;
5148         }
5149
5150         VectorCopy(normal, plane.normal);
5151         VectorNormalize(plane.normal);
5152         plane.dist = DotProduct(vert[0], plane.normal);
5153         PlaneClassify(&plane);
5154         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5155         {
5156                 // skip backfaces (except if nocullface is set)
5157                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5158                         return;
5159                 VectorNegate(plane.normal, plane.normal);
5160                 plane.dist *= -1;
5161                 PlaneClassify(&plane);
5162         }
5163
5164
5165         // find a matching plane if there is one
5166         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5167                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5168                         break;
5169         if (planeindex >= r_waterstate.maxwaterplanes)
5170                 return; // nothing we can do, out of planes
5171
5172         // if this triangle does not fit any known plane rendered this frame, add one
5173         if (planeindex >= r_waterstate.numwaterplanes)
5174         {
5175                 // store the new plane
5176                 r_waterstate.numwaterplanes++;
5177                 p->plane = plane;
5178                 // clear materialflags and pvs
5179                 p->materialflags = 0;
5180                 p->pvsvalid = false;
5181         }
5182         // merge this surface's materialflags into the waterplane
5183         p->materialflags |= t->currentmaterialflags;
5184         // merge this surface's PVS into the waterplane
5185         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5186         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5187          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5188         {
5189                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5190                 p->pvsvalid = true;
5191         }
5192 }
5193
5194 static void R_Water_ProcessPlanes(void)
5195 {
5196         r_refdef_view_t originalview;
5197         r_refdef_view_t myview;
5198         int planeindex;
5199         r_waterstate_waterplane_t *p;
5200
5201         originalview = r_refdef.view;
5202
5203         // make sure enough textures are allocated
5204         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5205         {
5206                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5207                 {
5208                         if (!p->texture_refraction)
5209                                 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);
5210                         if (!p->texture_refraction)
5211                                 goto error;
5212                 }
5213
5214                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5215                 {
5216                         if (!p->texture_reflection)
5217                                 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);
5218                         if (!p->texture_reflection)
5219                                 goto error;
5220                 }
5221         }
5222
5223         // render views
5224         r_refdef.view = originalview;
5225         r_refdef.view.showdebug = false;
5226         r_refdef.view.width = r_waterstate.waterwidth;
5227         r_refdef.view.height = r_waterstate.waterheight;
5228         r_refdef.view.useclipplane = true;
5229         myview = r_refdef.view;
5230         r_waterstate.renderingscene = true;
5231         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5232         {
5233                 // render the normal view scene and copy into texture
5234                 // (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)
5235                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5236                 {
5237                         r_refdef.view = myview;
5238                         r_refdef.view.clipplane = p->plane;
5239                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5240                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5241                         PlaneClassify(&r_refdef.view.clipplane);
5242
5243                         R_ResetViewRendering3D();
5244                         R_ClearScreen(r_refdef.fogenabled);
5245                         R_View_Update();
5246                         R_RenderScene();
5247
5248                         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);
5249                 }
5250
5251                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5252                 {
5253                         r_refdef.view = myview;
5254                         // render reflected scene and copy into texture
5255                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5256                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5257                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5258                         r_refdef.view.clipplane = p->plane;
5259                         // reverse the cullface settings for this render
5260                         r_refdef.view.cullface_front = GL_FRONT;
5261                         r_refdef.view.cullface_back = GL_BACK;
5262                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5263                         {
5264                                 r_refdef.view.usecustompvs = true;
5265                                 if (p->pvsvalid)
5266                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5267                                 else
5268                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5269                         }
5270
5271                         R_ResetViewRendering3D();
5272                         R_ClearScreen(r_refdef.fogenabled);
5273                         R_View_Update();
5274                         R_RenderScene();
5275
5276                         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);
5277                 }
5278         }
5279         r_waterstate.renderingscene = false;
5280         r_refdef.view = originalview;
5281         R_ResetViewRendering3D();
5282         R_ClearScreen(r_refdef.fogenabled);
5283         R_View_Update();
5284         return;
5285 error:
5286         r_refdef.view = originalview;
5287         r_waterstate.renderingscene = false;
5288         Cvar_SetValueQuick(&r_water, 0);
5289         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5290         return;
5291 }
5292
5293 void R_Bloom_StartFrame(void)
5294 {
5295         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5296
5297         switch(vid.renderpath)
5298         {
5299         case RENDERPATH_GL20:
5300         case RENDERPATH_CGGL:
5301                 break;
5302         case RENDERPATH_GL13:
5303         case RENDERPATH_GL11:
5304                 return;
5305         }
5306
5307         // set bloomwidth and bloomheight to the bloom resolution that will be
5308         // used (often less than the screen resolution for faster rendering)
5309         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5310         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5311         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5312         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5313         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5314
5315         // calculate desired texture sizes
5316         if (vid.support.arb_texture_non_power_of_two)
5317         {
5318                 screentexturewidth = r_refdef.view.width;
5319                 screentextureheight = r_refdef.view.height;
5320                 bloomtexturewidth = r_bloomstate.bloomwidth;
5321                 bloomtextureheight = r_bloomstate.bloomheight;
5322         }
5323         else
5324         {
5325                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5326                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5327                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5328                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5329         }
5330
5331         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))
5332         {
5333                 Cvar_SetValueQuick(&r_hdr, 0);
5334                 Cvar_SetValueQuick(&r_bloom, 0);
5335                 Cvar_SetValueQuick(&r_motionblur, 0);
5336                 Cvar_SetValueQuick(&r_damageblur, 0);
5337         }
5338
5339         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)))
5340                 screentexturewidth = screentextureheight = 0;
5341         if (!r_hdr.integer && !r_bloom.integer)
5342                 bloomtexturewidth = bloomtextureheight = 0;
5343
5344         // allocate textures as needed
5345         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5346         {
5347                 if (r_bloomstate.texture_screen)
5348                         R_FreeTexture(r_bloomstate.texture_screen);
5349                 r_bloomstate.texture_screen = NULL;
5350                 r_bloomstate.screentexturewidth = screentexturewidth;
5351                 r_bloomstate.screentextureheight = screentextureheight;
5352                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5353                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
5354         }
5355         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5356         {
5357                 if (r_bloomstate.texture_bloom)
5358                         R_FreeTexture(r_bloomstate.texture_bloom);
5359                 r_bloomstate.texture_bloom = NULL;
5360                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5361                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5362                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5363                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
5364         }
5365
5366         // when doing a reduced render (HDR) we want to use a smaller area
5367         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5368         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5369         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5370         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5371         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5372
5373         // set up a texcoord array for the full resolution screen image
5374         // (we have to keep this around to copy back during final render)
5375         r_bloomstate.screentexcoord2f[0] = 0;
5376         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5377         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5378         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5379         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5380         r_bloomstate.screentexcoord2f[5] = 0;
5381         r_bloomstate.screentexcoord2f[6] = 0;
5382         r_bloomstate.screentexcoord2f[7] = 0;
5383
5384         // set up a texcoord array for the reduced resolution bloom image
5385         // (which will be additive blended over the screen image)
5386         r_bloomstate.bloomtexcoord2f[0] = 0;
5387         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5388         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5389         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5390         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5391         r_bloomstate.bloomtexcoord2f[5] = 0;
5392         r_bloomstate.bloomtexcoord2f[6] = 0;
5393         r_bloomstate.bloomtexcoord2f[7] = 0;
5394
5395         if (r_hdr.integer || r_bloom.integer)
5396         {
5397                 r_bloomstate.enabled = true;
5398                 r_bloomstate.hdr = r_hdr.integer != 0;
5399         }
5400
5401         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);
5402 }
5403
5404 void R_Bloom_CopyBloomTexture(float colorscale)
5405 {
5406         r_refdef.stats.bloom++;
5407
5408         // scale down screen texture to the bloom texture size
5409         CHECKGLERROR
5410         R_SetViewport(&r_bloomstate.viewport);
5411         GL_BlendFunc(GL_ONE, GL_ZERO);
5412         GL_Color(colorscale, colorscale, colorscale, 1);
5413         // TODO: optimize with multitexture or GLSL
5414         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5415         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5416         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5417         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5418
5419         // we now have a bloom image in the framebuffer
5420         // copy it into the bloom image texture for later processing
5421         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);
5422         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5423 }
5424
5425 void R_Bloom_CopyHDRTexture(void)
5426 {
5427         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);
5428         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5429 }
5430
5431 void R_Bloom_MakeTexture(void)
5432 {
5433         int x, range, dir;
5434         float xoffset, yoffset, r, brighten;
5435
5436         r_refdef.stats.bloom++;
5437
5438         R_ResetViewRendering2D();
5439         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5440         R_Mesh_ColorPointer(NULL, 0, 0);
5441
5442         // we have a bloom image in the framebuffer
5443         CHECKGLERROR
5444         R_SetViewport(&r_bloomstate.viewport);
5445
5446         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5447         {
5448                 x *= 2;
5449                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5450                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5451                 GL_Color(r, r, r, 1);
5452                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5453                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5454                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5455                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5456
5457                 // copy the vertically blurred bloom view to a texture
5458                 GL_ActiveTexture(0);
5459                 CHECKGLERROR
5460                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
5461                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5462         }
5463
5464         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5465         brighten = r_bloom_brighten.value;
5466         if (r_hdr.integer)
5467                 brighten *= r_hdr_range.value;
5468         brighten = sqrt(brighten);
5469         if(range >= 1)
5470                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5471         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5472         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
5473
5474         for (dir = 0;dir < 2;dir++)
5475         {
5476                 // blend on at multiple vertical offsets to achieve a vertical blur
5477                 // TODO: do offset blends using GLSL
5478                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5479                 GL_BlendFunc(GL_ONE, GL_ZERO);
5480                 for (x = -range;x <= range;x++)
5481                 {
5482                         if (!dir){xoffset = 0;yoffset = x;}
5483                         else {xoffset = x;yoffset = 0;}
5484                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5485                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5486                         // compute a texcoord array with the specified x and y offset
5487                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5488                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5489                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5490                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5491                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5492                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5493                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5494                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5495                         // this r value looks like a 'dot' particle, fading sharply to
5496                         // black at the edges
5497                         // (probably not realistic but looks good enough)
5498                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5499                         //r = brighten/(range*2+1);
5500                         r = brighten / (range * 2 + 1);
5501                         if(range >= 1)
5502                                 r *= (1 - x*x/(float)(range*range));
5503                         GL_Color(r, r, r, 1);
5504                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5505                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5506                         GL_BlendFunc(GL_ONE, GL_ONE);
5507                 }
5508
5509                 // copy the vertically blurred bloom view to a texture
5510                 GL_ActiveTexture(0);
5511                 CHECKGLERROR
5512                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
5513                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5514         }
5515
5516         // apply subtract last
5517         // (just like it would be in a GLSL shader)
5518         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
5519         {
5520                 GL_BlendFunc(GL_ONE, GL_ZERO);
5521                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5522                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5523                 GL_Color(1, 1, 1, 1);
5524                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5525                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5526
5527                 GL_BlendFunc(GL_ONE, GL_ONE);
5528                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
5529                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5530                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5531                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
5532                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5533                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5534                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
5535
5536                 // copy the darkened bloom view to a texture
5537                 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);
5538                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5539         }
5540 }
5541
5542 void R_HDR_RenderBloomTexture(void)
5543 {
5544         int oldwidth, oldheight;
5545         float oldcolorscale;
5546
5547         oldcolorscale = r_refdef.view.colorscale;
5548         oldwidth = r_refdef.view.width;
5549         oldheight = r_refdef.view.height;
5550         r_refdef.view.width = r_bloomstate.bloomwidth;
5551         r_refdef.view.height = r_bloomstate.bloomheight;
5552
5553         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5554         // TODO: add exposure compensation features
5555         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5556
5557         r_refdef.view.showdebug = false;
5558         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5559
5560         R_ResetViewRendering3D();
5561
5562         R_ClearScreen(r_refdef.fogenabled);
5563         if (r_timereport_active)
5564                 R_TimeReport("HDRclear");
5565
5566         R_View_Update();
5567         if (r_timereport_active)
5568                 R_TimeReport("visibility");
5569
5570         // only do secondary renders with HDR if r_hdr is 2 or higher
5571         r_waterstate.numwaterplanes = 0;
5572         if (r_waterstate.enabled && r_hdr.integer >= 2)
5573                 R_RenderWaterPlanes();
5574
5575         r_refdef.view.showdebug = true;
5576         R_RenderScene();
5577         r_waterstate.numwaterplanes = 0;
5578
5579         R_ResetViewRendering2D();
5580
5581         R_Bloom_CopyHDRTexture();
5582         R_Bloom_MakeTexture();
5583
5584         // restore the view settings
5585         r_refdef.view.width = oldwidth;
5586         r_refdef.view.height = oldheight;
5587         r_refdef.view.colorscale = oldcolorscale;
5588         r_frame++; // used only by R_GetCurrentTexture
5589
5590         R_ResetViewRendering3D();
5591
5592         R_ClearScreen(r_refdef.fogenabled);
5593         if (r_timereport_active)
5594                 R_TimeReport("viewclear");
5595 }
5596
5597 static void R_BlendView(void)
5598 {
5599         unsigned int permutation;
5600         float uservecs[4][4];
5601
5602         switch (vid.renderpath)
5603         {
5604         case RENDERPATH_GL20:
5605         case RENDERPATH_CGGL:
5606                 permutation =
5607                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5608                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5609                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5610                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5611                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5612
5613                 if (r_bloomstate.texture_screen)
5614                 {
5615                         // make sure the buffer is available
5616                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5617
5618                         R_ResetViewRendering2D();
5619                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5620                         R_Mesh_ColorPointer(NULL, 0, 0);
5621
5622                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5623                         {
5624                                 // declare variables
5625                                 float speed;
5626                                 static float avgspeed;
5627
5628                                 speed = VectorLength(cl.movement_velocity);
5629
5630                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5631                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5632
5633                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5634                                 speed = bound(0, speed, 1);
5635                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5636
5637                                 // calculate values into a standard alpha
5638                                 cl.motionbluralpha = 1 - exp(-
5639                                                 (
5640                                                  (r_motionblur.value * speed / 80)
5641                                                  +
5642                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5643                                                 )
5644                                                 /
5645                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5646                                            );
5647
5648                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5649                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5650                                 // apply the blur
5651                                 if (cl.motionbluralpha > 0)
5652                                 {
5653                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5654                                         GL_Color(1, 1, 1, cl.motionbluralpha);
5655                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5656                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5657                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5658                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5659                                 }
5660                         }
5661
5662                         // copy view into the screen texture
5663                         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);
5664                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5665                 }
5666                 else if (!r_bloomstate.texture_bloom)
5667                 {
5668                         // we may still have to do view tint...
5669                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
5670                         {
5671                                 // apply a color tint to the whole view
5672                                 R_ResetViewRendering2D();
5673                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5674                                 R_Mesh_ColorPointer(NULL, 0, 0);
5675                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5676                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5677                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5678                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5679                         }
5680                         break; // no screen processing, no bloom, skip it
5681                 }
5682
5683                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
5684                 {
5685                         // render simple bloom effect
5686                         // copy the screen and shrink it and darken it for the bloom process
5687                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
5688                         // make the bloom texture
5689                         R_Bloom_MakeTexture();
5690                 }
5691
5692 #if _MSC_VER >= 1400
5693 #define sscanf sscanf_s
5694 #endif
5695                 memset(uservecs, 0, sizeof(uservecs));
5696                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
5697                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
5698                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
5699                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
5700
5701                 R_ResetViewRendering2D();
5702                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5703                 R_Mesh_ColorPointer(NULL, 0, 0);
5704                 GL_Color(1, 1, 1, 1);
5705                 GL_BlendFunc(GL_ONE, GL_ZERO);
5706                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5707                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5708
5709                 switch(vid.renderpath)
5710                 {
5711                 case RENDERPATH_GL20:
5712                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
5713                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , R_GetTexture(r_bloomstate.texture_screen));
5714                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , R_GetTexture(r_bloomstate.texture_bloom ));
5715                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps       ));
5716                         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]);
5717                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
5718                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
5719                         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]);
5720                         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]);
5721                         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]);
5722                         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]);
5723                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
5724                         break;
5725                 case RENDERPATH_CGGL:
5726 #ifdef SUPPORTCG
5727                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
5728                         if (r_cg_permutation->fp_Texture_First     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First     , R_GetTexture(r_bloomstate.texture_screen));
5729                         if (r_cg_permutation->fp_Texture_Second    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second    , R_GetTexture(r_bloomstate.texture_bloom ));
5730                         if (r_cg_permutation->fp_Texture_GammaRamps) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_GammaRamps, R_GetTexture(r_texture_gammaramps       ));
5731                         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]);
5732                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);
5733                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
5734                         if (r_cg_permutation->fp_UserVec1          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
5735                         if (r_cg_permutation->fp_UserVec2          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
5736                         if (r_cg_permutation->fp_UserVec3          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
5737                         if (r_cg_permutation->fp_UserVec4          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
5738                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);
5739 #endif
5740                         break;
5741                 default:
5742                         break;
5743                 }
5744                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5745                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5746                 break;
5747         case RENDERPATH_GL13:
5748         case RENDERPATH_GL11:
5749                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
5750                 {
5751                         // apply a color tint to the whole view
5752                         R_ResetViewRendering2D();
5753                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5754                         R_Mesh_ColorPointer(NULL, 0, 0);
5755                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5756                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5757                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5758                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5759                 }
5760                 break;
5761         }
5762 }
5763
5764 matrix4x4_t r_waterscrollmatrix;
5765
5766 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
5767 {
5768         if (r_refdef.fog_density)
5769         {
5770                 r_refdef.fogcolor[0] = r_refdef.fog_red;
5771                 r_refdef.fogcolor[1] = r_refdef.fog_green;
5772                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5773
5774                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5775                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5776                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5777                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5778
5779                 {
5780                         vec3_t fogvec;
5781                         VectorCopy(r_refdef.fogcolor, fogvec);
5782                         //   color.rgb *= ContrastBoost * SceneBrightness;
5783                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5784                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5785                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5786                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5787                 }
5788         }
5789 }
5790
5791 void R_UpdateVariables(void)
5792 {
5793         R_Textures_Frame();
5794
5795         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
5796
5797         r_refdef.farclip = r_farclip_base.value;
5798         if (r_refdef.scene.worldmodel)
5799                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5800         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5801
5802         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5803                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5804         r_refdef.polygonfactor = 0;
5805         r_refdef.polygonoffset = 0;
5806         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5807         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5808
5809         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5810         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5811         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5812         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5813         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5814         if (r_showsurfaces.integer)
5815         {
5816                 r_refdef.scene.rtworld = false;
5817                 r_refdef.scene.rtworldshadows = false;
5818                 r_refdef.scene.rtdlight = false;
5819                 r_refdef.scene.rtdlightshadows = false;
5820                 r_refdef.lightmapintensity = 0;
5821         }
5822
5823         if (gamemode == GAME_NEHAHRA)
5824         {
5825                 if (gl_fogenable.integer)
5826                 {
5827                         r_refdef.oldgl_fogenable = true;
5828                         r_refdef.fog_density = gl_fogdensity.value;
5829                         r_refdef.fog_red = gl_fogred.value;
5830                         r_refdef.fog_green = gl_foggreen.value;
5831                         r_refdef.fog_blue = gl_fogblue.value;
5832                         r_refdef.fog_alpha = 1;
5833                         r_refdef.fog_start = 0;
5834                         r_refdef.fog_end = gl_skyclip.value;
5835                         r_refdef.fog_height = 1<<30;
5836                         r_refdef.fog_fadedepth = 128;
5837                 }
5838                 else if (r_refdef.oldgl_fogenable)
5839                 {
5840                         r_refdef.oldgl_fogenable = false;
5841                         r_refdef.fog_density = 0;
5842                         r_refdef.fog_red = 0;
5843                         r_refdef.fog_green = 0;
5844                         r_refdef.fog_blue = 0;
5845                         r_refdef.fog_alpha = 0;
5846                         r_refdef.fog_start = 0;
5847                         r_refdef.fog_end = 0;
5848                         r_refdef.fog_height = 1<<30;
5849                         r_refdef.fog_fadedepth = 128;
5850                 }
5851         }
5852
5853         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5854         r_refdef.fog_start = max(0, r_refdef.fog_start);
5855         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5856
5857         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5858
5859         if (r_refdef.fog_density && r_drawfog.integer)
5860         {
5861                 r_refdef.fogenabled = true;
5862                 // this is the point where the fog reaches 0.9986 alpha, which we
5863                 // consider a good enough cutoff point for the texture
5864                 // (0.9986 * 256 == 255.6)
5865                 if (r_fog_exp2.integer)
5866                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5867                 else
5868                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5869                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5870                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5871                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5872                 // fog color was already set
5873                 // update the fog texture
5874                 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)
5875                         R_BuildFogTexture();
5876         }
5877         else
5878                 r_refdef.fogenabled = false;
5879
5880         switch(vid.renderpath)
5881         {
5882         case RENDERPATH_GL20:
5883         case RENDERPATH_CGGL:
5884                 if(v_glslgamma.integer && !vid_gammatables_trivial)
5885                 {
5886                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5887                         {
5888                                 // build GLSL gamma texture
5889 #define RAMPWIDTH 256
5890                                 unsigned short ramp[RAMPWIDTH * 3];
5891                                 unsigned char rampbgr[RAMPWIDTH][4];
5892                                 int i;
5893
5894                                 r_texture_gammaramps_serial = vid_gammatables_serial;
5895
5896                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5897                                 for(i = 0; i < RAMPWIDTH; ++i)
5898                                 {
5899                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5900                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5901                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5902                                         rampbgr[i][3] = 0;
5903                                 }
5904                                 if (r_texture_gammaramps)
5905                                 {
5906                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5907                                 }
5908                                 else
5909                                 {
5910                                         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);
5911                                 }
5912                         }
5913                 }
5914                 else
5915                 {
5916                         // remove GLSL gamma texture
5917                 }
5918                 break;
5919         case RENDERPATH_GL13:
5920         case RENDERPATH_GL11:
5921                 break;
5922         }
5923 }
5924
5925 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5926 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5927 /*
5928 ================
5929 R_SelectScene
5930 ================
5931 */
5932 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5933         if( scenetype != r_currentscenetype ) {
5934                 // store the old scenetype
5935                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5936                 r_currentscenetype = scenetype;
5937                 // move in the new scene
5938                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5939         }
5940 }
5941
5942 /*
5943 ================
5944 R_GetScenePointer
5945 ================
5946 */
5947 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5948 {
5949         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5950         if( scenetype == r_currentscenetype ) {
5951                 return &r_refdef.scene;
5952         } else {
5953                 return &r_scenes_store[ scenetype ];
5954         }
5955 }
5956
5957 /*
5958 ================
5959 R_RenderView
5960 ================
5961 */
5962 void R_RenderView(void)
5963 {
5964         if (r_timereport_active)
5965                 R_TimeReport("start");
5966         r_frame++; // used only by R_GetCurrentTexture
5967         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5968
5969         if (!r_drawentities.integer)
5970                 r_refdef.scene.numentities = 0;
5971
5972         R_AnimCache_ClearCache();
5973         R_FrameData_NewFrame();
5974
5975         if (r_refdef.view.isoverlay)
5976         {
5977                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5978                 GL_Clear( GL_DEPTH_BUFFER_BIT );
5979                 R_TimeReport("depthclear");
5980
5981                 r_refdef.view.showdebug = false;
5982
5983                 r_waterstate.enabled = false;
5984                 r_waterstate.numwaterplanes = 0;
5985
5986                 R_RenderScene();
5987
5988                 CHECKGLERROR
5989                 return;
5990         }
5991
5992         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
5993                 return; //Host_Error ("R_RenderView: NULL worldmodel");
5994
5995         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
5996
5997         // break apart the view matrix into vectors for various purposes
5998         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5999         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
6000         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
6001         VectorNegate(r_refdef.view.left, r_refdef.view.right);
6002         // make an inverted copy of the view matrix for tracking sprites
6003         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
6004
6005         R_Shadow_UpdateWorldLightSelection();
6006
6007         R_Bloom_StartFrame();
6008         R_Water_StartFrame();
6009
6010         CHECKGLERROR
6011         if (r_timereport_active)
6012                 R_TimeReport("viewsetup");
6013
6014         R_ResetViewRendering3D();
6015
6016         if (r_refdef.view.clear || r_refdef.fogenabled)
6017         {
6018                 R_ClearScreen(r_refdef.fogenabled);
6019                 if (r_timereport_active)
6020                         R_TimeReport("viewclear");
6021         }
6022         r_refdef.view.clear = true;
6023
6024         // this produces a bloom texture to be used in R_BlendView() later
6025         if (r_hdr.integer && r_bloomstate.bloomwidth)
6026                 R_HDR_RenderBloomTexture();
6027
6028         r_refdef.view.showdebug = true;
6029
6030         R_View_Update();
6031         if (r_timereport_active)
6032                 R_TimeReport("visibility");
6033
6034         r_waterstate.numwaterplanes = 0;
6035         if (r_waterstate.enabled)
6036                 R_RenderWaterPlanes();
6037
6038         R_RenderScene();
6039         r_waterstate.numwaterplanes = 0;
6040
6041         R_BlendView();
6042         if (r_timereport_active)
6043                 R_TimeReport("blendview");
6044
6045         GL_Scissor(0, 0, vid.width, vid.height);
6046         GL_ScissorTest(false);
6047         CHECKGLERROR
6048 }
6049
6050 void R_RenderWaterPlanes(void)
6051 {
6052         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6053         {
6054                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6055                 if (r_timereport_active)
6056                         R_TimeReport("waterworld");
6057         }
6058
6059         // don't let sound skip if going slow
6060         if (r_refdef.scene.extraupdate)
6061                 S_ExtraUpdate ();
6062
6063         R_DrawModelsAddWaterPlanes();
6064         if (r_timereport_active)
6065                 R_TimeReport("watermodels");
6066
6067         if (r_waterstate.numwaterplanes)
6068         {
6069                 R_Water_ProcessPlanes();
6070                 if (r_timereport_active)
6071                         R_TimeReport("waterscenes");
6072         }
6073 }
6074
6075 extern void R_DrawLightningBeams (void);
6076 extern void VM_CL_AddPolygonsToMeshQueue (void);
6077 extern void R_DrawPortals (void);
6078 extern cvar_t cl_locs_show;
6079 static void R_DrawLocs(void);
6080 static void R_DrawEntityBBoxes(void);
6081 static void R_DrawModelDecals(void);
6082 extern cvar_t cl_decals_newsystem;
6083 extern qboolean r_shadow_usingdeferredprepass;
6084 void R_RenderScene(void)
6085 {
6086         r_refdef.stats.renders++;
6087
6088         R_UpdateFogColor();
6089
6090         // don't let sound skip if going slow
6091         if (r_refdef.scene.extraupdate)
6092                 S_ExtraUpdate ();
6093
6094         R_MeshQueue_BeginScene();
6095
6096         R_SkyStartFrame();
6097
6098         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);
6099
6100         if (cl.csqc_vidvars.drawworld)
6101         {
6102                 // don't let sound skip if going slow
6103                 if (r_refdef.scene.extraupdate)
6104                         S_ExtraUpdate ();
6105
6106                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6107                 {
6108                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6109                         if (r_timereport_active)
6110                                 R_TimeReport("worldsky");
6111                 }
6112
6113                 if (R_DrawBrushModelsSky() && r_timereport_active)
6114                         R_TimeReport("bmodelsky");
6115
6116                 if (skyrendermasked && skyrenderlater)
6117                 {
6118                         // we have to force off the water clipping plane while rendering sky
6119                         R_SetupView(false);
6120                         R_Sky();
6121                         R_SetupView(true);
6122                         if (r_timereport_active)
6123                                 R_TimeReport("sky");
6124                 }
6125         }
6126
6127         R_AnimCache_CacheVisibleEntities();
6128         if (r_timereport_active)
6129                 R_TimeReport("animation");
6130
6131         R_Shadow_PrepareLights();
6132         if (r_timereport_active)
6133                 R_TimeReport("preparelights");
6134
6135         if (r_shadow_usingdeferredprepass)
6136                 R_Shadow_DrawPrepass();
6137
6138         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6139         {
6140                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6141                 if (r_timereport_active)
6142                         R_TimeReport("worlddepth");
6143         }
6144         if (r_depthfirst.integer >= 2)
6145         {
6146                 R_DrawModelsDepth();
6147                 if (r_timereport_active)
6148                         R_TimeReport("modeldepth");
6149         }
6150
6151         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6152         {
6153                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6154                 if (r_timereport_active)
6155                         R_TimeReport("world");
6156         }
6157
6158         // don't let sound skip if going slow
6159         if (r_refdef.scene.extraupdate)
6160                 S_ExtraUpdate ();
6161
6162         R_DrawModels();
6163         if (r_timereport_active)
6164                 R_TimeReport("models");
6165
6166         // don't let sound skip if going slow
6167         if (r_refdef.scene.extraupdate)
6168                 S_ExtraUpdate ();
6169
6170         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6171         {
6172                 R_DrawModelShadows();
6173                 R_ResetViewRendering3D();
6174                 // don't let sound skip if going slow
6175                 if (r_refdef.scene.extraupdate)
6176                         S_ExtraUpdate ();
6177         }
6178
6179         if (!r_shadow_usingdeferredprepass)
6180         {
6181                 R_Shadow_DrawLights();
6182                 if (r_timereport_active)
6183                         R_TimeReport("rtlights");
6184         }
6185
6186         // don't let sound skip if going slow
6187         if (r_refdef.scene.extraupdate)
6188                 S_ExtraUpdate ();
6189
6190         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6191         {
6192                 R_DrawModelShadows();
6193                 R_ResetViewRendering3D();
6194                 // don't let sound skip if going slow
6195                 if (r_refdef.scene.extraupdate)
6196                         S_ExtraUpdate ();
6197         }
6198
6199         if (cl.csqc_vidvars.drawworld)
6200         {
6201                 if (cl_decals_newsystem.integer)
6202                 {
6203                         R_DrawModelDecals();
6204                         if (r_timereport_active)
6205                                 R_TimeReport("modeldecals");
6206                 }
6207                 else
6208                 {
6209                         R_DrawDecals();
6210                         if (r_timereport_active)
6211                                 R_TimeReport("decals");
6212                 }
6213
6214                 R_DrawParticles();
6215                 if (r_timereport_active)
6216                         R_TimeReport("particles");
6217
6218                 R_DrawExplosions();
6219                 if (r_timereport_active)
6220                         R_TimeReport("explosions");
6221
6222                 R_DrawLightningBeams();
6223                 if (r_timereport_active)
6224                         R_TimeReport("lightning");
6225         }
6226
6227         VM_CL_AddPolygonsToMeshQueue();
6228
6229         if (r_refdef.view.showdebug)
6230         {
6231                 if (cl_locs_show.integer)
6232                 {
6233                         R_DrawLocs();
6234                         if (r_timereport_active)
6235                                 R_TimeReport("showlocs");
6236                 }
6237
6238                 if (r_drawportals.integer)
6239                 {
6240                         R_DrawPortals();
6241                         if (r_timereport_active)
6242                                 R_TimeReport("portals");
6243                 }
6244
6245                 if (r_showbboxes.value > 0)
6246                 {
6247                         R_DrawEntityBBoxes();
6248                         if (r_timereport_active)
6249                                 R_TimeReport("bboxes");
6250                 }
6251         }
6252
6253         R_MeshQueue_RenderTransparent();
6254         if (r_timereport_active)
6255                 R_TimeReport("drawtrans");
6256
6257         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))
6258         {
6259                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6260                 if (r_timereport_active)
6261                         R_TimeReport("worlddebug");
6262                 R_DrawModelsDebug();
6263                 if (r_timereport_active)
6264                         R_TimeReport("modeldebug");
6265         }
6266
6267         if (cl.csqc_vidvars.drawworld)
6268         {
6269                 R_Shadow_DrawCoronas();
6270                 if (r_timereport_active)
6271                         R_TimeReport("coronas");
6272         }
6273
6274         // don't let sound skip if going slow
6275         if (r_refdef.scene.extraupdate)
6276                 S_ExtraUpdate ();
6277
6278         R_ResetViewRendering2D();
6279 }
6280
6281 static const unsigned short bboxelements[36] =
6282 {
6283         5, 1, 3, 5, 3, 7,
6284         6, 2, 0, 6, 0, 4,
6285         7, 3, 2, 7, 2, 6,
6286         4, 0, 1, 4, 1, 5,
6287         4, 5, 7, 4, 7, 6,
6288         1, 0, 2, 1, 2, 3,
6289 };
6290
6291 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6292 {
6293         int i;
6294         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6295
6296         RSurf_ActiveWorldEntity();
6297
6298         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6299         GL_DepthMask(false);
6300         GL_DepthRange(0, 1);
6301         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6302         R_Mesh_ResetTextureState();
6303
6304         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6305         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6306         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6307         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6308         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6309         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6310         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6311         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6312         R_FillColors(color4f, 8, cr, cg, cb, ca);
6313         if (r_refdef.fogenabled)
6314         {
6315                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6316                 {
6317                         f1 = RSurf_FogVertex(v);
6318                         f2 = 1 - f1;
6319                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6320                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6321                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6322                 }
6323         }
6324         R_Mesh_VertexPointer(vertex3f, 0, 0);
6325         R_Mesh_ColorPointer(color4f, 0, 0);
6326         R_Mesh_ResetTextureState();
6327         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6328         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
6329 }
6330
6331 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6332 {
6333         int i;
6334         float color[4];
6335         prvm_edict_t *edict;
6336         prvm_prog_t *prog_save = prog;
6337
6338         // this function draws bounding boxes of server entities
6339         if (!sv.active)
6340                 return;
6341
6342         GL_CullFace(GL_NONE);
6343         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6344
6345         prog = 0;
6346         SV_VM_Begin();
6347         for (i = 0;i < numsurfaces;i++)
6348         {
6349                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6350                 switch ((int)edict->fields.server->solid)
6351                 {
6352                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6353                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6354                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6355                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6356                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6357                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6358                 }
6359                 color[3] *= r_showbboxes.value;
6360                 color[3] = bound(0, color[3], 1);
6361                 GL_DepthTest(!r_showdisabledepthtest.integer);
6362                 GL_CullFace(r_refdef.view.cullface_front);
6363                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6364         }
6365         SV_VM_End();
6366         prog = prog_save;
6367 }
6368
6369 static void R_DrawEntityBBoxes(void)
6370 {
6371         int i;
6372         prvm_edict_t *edict;
6373         vec3_t center;
6374         prvm_prog_t *prog_save = prog;
6375
6376         // this function draws bounding boxes of server entities
6377         if (!sv.active)
6378                 return;
6379
6380         prog = 0;
6381         SV_VM_Begin();
6382         for (i = 0;i < prog->num_edicts;i++)
6383         {
6384                 edict = PRVM_EDICT_NUM(i);
6385                 if (edict->priv.server->free)
6386                         continue;
6387                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6388                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6389                         continue;
6390                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6391                         continue;
6392                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6393                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6394         }
6395         SV_VM_End();
6396         prog = prog_save;
6397 }
6398
6399 static const int nomodelelement3i[24] =
6400 {
6401         5, 2, 0,
6402         5, 1, 2,
6403         5, 0, 3,
6404         5, 3, 1,
6405         0, 2, 4,
6406         2, 1, 4,
6407         3, 0, 4,
6408         1, 3, 4
6409 };
6410
6411 static const unsigned short nomodelelement3s[24] =
6412 {
6413         5, 2, 0,
6414         5, 1, 2,
6415         5, 0, 3,
6416         5, 3, 1,
6417         0, 2, 4,
6418         2, 1, 4,
6419         3, 0, 4,
6420         1, 3, 4
6421 };
6422
6423 static const float nomodelvertex3f[6*3] =
6424 {
6425         -16,   0,   0,
6426          16,   0,   0,
6427           0, -16,   0,
6428           0,  16,   0,
6429           0,   0, -16,
6430           0,   0,  16
6431 };
6432
6433 static const float nomodelcolor4f[6*4] =
6434 {
6435         0.0f, 0.0f, 0.5f, 1.0f,
6436         0.0f, 0.0f, 0.5f, 1.0f,
6437         0.0f, 0.5f, 0.0f, 1.0f,
6438         0.0f, 0.5f, 0.0f, 1.0f,
6439         0.5f, 0.0f, 0.0f, 1.0f,
6440         0.5f, 0.0f, 0.0f, 1.0f
6441 };
6442
6443 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6444 {
6445         int i;
6446         float f1, f2, *c;
6447         float color4f[6*4];
6448
6449         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);
6450
6451         // this is only called once per entity so numsurfaces is always 1, and
6452         // surfacelist is always {0}, so this code does not handle batches
6453
6454         if (rsurface.ent_flags & RENDER_ADDITIVE)
6455         {
6456                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6457                 GL_DepthMask(false);
6458         }
6459         else if (rsurface.colormod[3] < 1)
6460         {
6461                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6462                 GL_DepthMask(false);
6463         }
6464         else
6465         {
6466                 GL_BlendFunc(GL_ONE, GL_ZERO);
6467                 GL_DepthMask(true);
6468         }
6469         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6470         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6471         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6472         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6473         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6474         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6475         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6476         R_Mesh_ColorPointer(color4f, 0, 0);
6477         for (i = 0, c = color4f;i < 6;i++, c += 4)
6478         {
6479                 c[0] *= rsurface.colormod[0];
6480                 c[1] *= rsurface.colormod[1];
6481                 c[2] *= rsurface.colormod[2];
6482                 c[3] *= rsurface.colormod[3];
6483         }
6484         if (r_refdef.fogenabled)
6485         {
6486                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6487                 {
6488                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
6489                         f2 = 1 - f1;
6490                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6491                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6492                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6493                 }
6494         }
6495         R_Mesh_ResetTextureState();
6496         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
6497 }
6498
6499 void R_DrawNoModel(entity_render_t *ent)
6500 {
6501         vec3_t org;
6502         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6503         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6504                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6505         else
6506                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6507 }
6508
6509 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6510 {
6511         vec3_t right1, right2, diff, normal;
6512
6513         VectorSubtract (org2, org1, normal);
6514
6515         // calculate 'right' vector for start
6516         VectorSubtract (r_refdef.view.origin, org1, diff);
6517         CrossProduct (normal, diff, right1);
6518         VectorNormalize (right1);
6519
6520         // calculate 'right' vector for end
6521         VectorSubtract (r_refdef.view.origin, org2, diff);
6522         CrossProduct (normal, diff, right2);
6523         VectorNormalize (right2);
6524
6525         vert[ 0] = org1[0] + width * right1[0];
6526         vert[ 1] = org1[1] + width * right1[1];
6527         vert[ 2] = org1[2] + width * right1[2];
6528         vert[ 3] = org1[0] - width * right1[0];
6529         vert[ 4] = org1[1] - width * right1[1];
6530         vert[ 5] = org1[2] - width * right1[2];
6531         vert[ 6] = org2[0] - width * right2[0];
6532         vert[ 7] = org2[1] - width * right2[1];
6533         vert[ 8] = org2[2] - width * right2[2];
6534         vert[ 9] = org2[0] + width * right2[0];
6535         vert[10] = org2[1] + width * right2[1];
6536         vert[11] = org2[2] + width * right2[2];
6537 }
6538
6539 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)
6540 {
6541         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6542         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6543         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6544         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6545         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6546         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6547         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6548         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6549         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6550         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6551         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6552         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
6553 }
6554
6555 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
6556 {
6557         int i;
6558         float *vertex3f;
6559         float v[3];
6560         VectorSet(v, x, y, z);
6561         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
6562                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
6563                         break;
6564         if (i == mesh->numvertices)
6565         {
6566                 if (mesh->numvertices < mesh->maxvertices)
6567                 {
6568                         VectorCopy(v, vertex3f);
6569                         mesh->numvertices++;
6570                 }
6571                 return mesh->numvertices;
6572         }
6573         else
6574                 return i;
6575 }
6576
6577 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
6578 {
6579         int i;
6580         int *e, element[3];
6581         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6582         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6583         e = mesh->element3i + mesh->numtriangles * 3;
6584         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
6585         {
6586                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
6587                 if (mesh->numtriangles < mesh->maxtriangles)
6588                 {
6589                         *e++ = element[0];
6590                         *e++ = element[1];
6591                         *e++ = element[2];
6592                         mesh->numtriangles++;
6593                 }
6594                 element[1] = element[2];
6595         }
6596 }
6597
6598 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
6599 {
6600         int i;
6601         int *e, element[3];
6602         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6603         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6604         e = mesh->element3i + mesh->numtriangles * 3;
6605         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
6606         {
6607                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
6608                 if (mesh->numtriangles < mesh->maxtriangles)
6609                 {
6610                         *e++ = element[0];
6611                         *e++ = element[1];
6612                         *e++ = element[2];
6613                         mesh->numtriangles++;
6614                 }
6615                 element[1] = element[2];
6616         }
6617 }
6618
6619 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
6620 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
6621 {
6622         int planenum, planenum2;
6623         int w;
6624         int tempnumpoints;
6625         mplane_t *plane, *plane2;
6626         double maxdist;
6627         double temppoints[2][256*3];
6628         // figure out how large a bounding box we need to properly compute this brush
6629         maxdist = 0;
6630         for (w = 0;w < numplanes;w++)
6631                 maxdist = max(maxdist, fabs(planes[w].dist));
6632         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
6633         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
6634         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
6635         {
6636                 w = 0;
6637                 tempnumpoints = 4;
6638                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
6639                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
6640                 {
6641                         if (planenum2 == planenum)
6642                                 continue;
6643                         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);
6644                         w = !w;
6645                 }
6646                 if (tempnumpoints < 3)
6647                         continue;
6648                 // generate elements forming a triangle fan for this polygon
6649                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
6650         }
6651 }
6652
6653 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)
6654 {
6655         texturelayer_t *layer;
6656         layer = t->currentlayers + t->currentnumlayers++;
6657         layer->type = type;
6658         layer->depthmask = depthmask;
6659         layer->blendfunc1 = blendfunc1;
6660         layer->blendfunc2 = blendfunc2;
6661         layer->texture = texture;
6662         layer->texmatrix = *matrix;
6663         layer->color[0] = r;
6664         layer->color[1] = g;
6665         layer->color[2] = b;
6666         layer->color[3] = a;
6667 }
6668
6669 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
6670 {
6671         double index, f;
6672         index = parms[2] + r_refdef.scene.time * parms[3];
6673         index -= floor(index);
6674         switch (func)
6675         {
6676         default:
6677         case Q3WAVEFUNC_NONE:
6678         case Q3WAVEFUNC_NOISE:
6679         case Q3WAVEFUNC_COUNT:
6680                 f = 0;
6681                 break;
6682         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
6683         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
6684         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
6685         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
6686         case Q3WAVEFUNC_TRIANGLE:
6687                 index *= 4;
6688                 f = index - floor(index);
6689                 if (index < 1)
6690                         f = f;
6691                 else if (index < 2)
6692                         f = 1 - f;
6693                 else if (index < 3)
6694                         f = -f;
6695                 else
6696                         f = -(1 - f);
6697                 break;
6698         }
6699         return (float)(parms[0] + parms[1] * f);
6700 }
6701
6702 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
6703 {
6704         int w, h, idx;
6705         float f;
6706         float tcmat[12];
6707         matrix4x4_t matrix, temp;
6708         switch(tcmod->tcmod)
6709         {
6710                 case Q3TCMOD_COUNT:
6711                 case Q3TCMOD_NONE:
6712                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6713                                 matrix = r_waterscrollmatrix;
6714                         else
6715                                 matrix = identitymatrix;
6716                         break;
6717                 case Q3TCMOD_ENTITYTRANSLATE:
6718                         // this is used in Q3 to allow the gamecode to control texcoord
6719                         // scrolling on the entity, which is not supported in darkplaces yet.
6720                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
6721                         break;
6722                 case Q3TCMOD_ROTATE:
6723                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
6724                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
6725                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
6726                         break;
6727                 case Q3TCMOD_SCALE:
6728                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
6729                         break;
6730                 case Q3TCMOD_SCROLL:
6731                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
6732                         break;
6733                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
6734                         w = (int) tcmod->parms[0];
6735                         h = (int) tcmod->parms[1];
6736                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
6737                         f = f - floor(f);
6738                         idx = (int) floor(f * w * h);
6739                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
6740                         break;
6741                 case Q3TCMOD_STRETCH:
6742                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
6743                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
6744                         break;
6745                 case Q3TCMOD_TRANSFORM:
6746                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
6747                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
6748                         VectorSet(tcmat +  6, 0                   , 0                , 1);
6749                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
6750                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
6751                         break;
6752                 case Q3TCMOD_TURBULENT:
6753                         // this is handled in the RSurf_PrepareVertices function
6754                         matrix = identitymatrix;
6755                         break;
6756         }
6757         temp = *texmatrix;
6758         Matrix4x4_Concat(texmatrix, &matrix, &temp);
6759 }
6760
6761 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
6762 {
6763         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
6764         char name[MAX_QPATH];
6765         skinframe_t *skinframe;
6766         unsigned char pixels[296*194];
6767         strlcpy(cache->name, skinname, sizeof(cache->name));
6768         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6769         if (developer_loading.integer)
6770                 Con_Printf("loading %s\n", name);
6771         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6772         if (!skinframe || !skinframe->base)
6773         {
6774                 unsigned char *f;
6775                 fs_offset_t filesize;
6776                 skinframe = NULL;
6777                 f = FS_LoadFile(name, tempmempool, true, &filesize);
6778                 if (f)
6779                 {
6780                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
6781                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6782                         Mem_Free(f);
6783                 }
6784         }
6785         cache->skinframe = skinframe;
6786 }
6787
6788 texture_t *R_GetCurrentTexture(texture_t *t)
6789 {
6790         int i;
6791         const entity_render_t *ent = rsurface.entity;
6792         dp_model_t *model = ent->model;
6793         q3shaderinfo_layer_tcmod_t *tcmod;
6794
6795         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
6796                 return t->currentframe;
6797         t->update_lastrenderframe = r_frame;
6798         t->update_lastrenderentity = (void *)ent;
6799
6800         // switch to an alternate material if this is a q1bsp animated material
6801         {
6802                 texture_t *texture = t;
6803                 int s = rsurface.ent_skinnum;
6804                 if ((unsigned int)s >= (unsigned int)model->numskins)
6805                         s = 0;
6806                 if (model->skinscenes)
6807                 {
6808                         if (model->skinscenes[s].framecount > 1)
6809                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6810                         else
6811                                 s = model->skinscenes[s].firstframe;
6812                 }
6813                 if (s > 0)
6814                         t = t + s * model->num_surfaces;
6815                 if (t->animated)
6816                 {
6817                         // use an alternate animation if the entity's frame is not 0,
6818                         // and only if the texture has an alternate animation
6819                         if (rsurface.ent_alttextures && t->anim_total[1])
6820                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6821                         else
6822                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6823                 }
6824                 texture->currentframe = t;
6825         }
6826
6827         // update currentskinframe to be a qw skin or animation frame
6828         if (rsurface.ent_qwskin >= 0)
6829         {
6830                 i = rsurface.ent_qwskin;
6831                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6832                 {
6833                         r_qwskincache_size = cl.maxclients;
6834                         if (r_qwskincache)
6835                                 Mem_Free(r_qwskincache);
6836                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6837                 }
6838                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6839                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6840                 t->currentskinframe = r_qwskincache[i].skinframe;
6841                 if (t->currentskinframe == NULL)
6842                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6843         }
6844         else if (t->numskinframes >= 2)
6845                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6846         if (t->backgroundnumskinframes >= 2)
6847                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6848
6849         t->currentmaterialflags = t->basematerialflags;
6850         t->currentalpha = rsurface.colormod[3];
6851         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6852                 t->currentalpha *= r_wateralpha.value;
6853         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6854                 t->currentalpha *= t->r_water_wateralpha;
6855         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6856                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6857         if (!(rsurface.ent_flags & RENDER_LIGHT))
6858                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6859         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6860         {
6861                 // pick a model lighting mode
6862                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6863                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6864                 else
6865                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6866         }
6867         if (rsurface.ent_flags & RENDER_ADDITIVE)
6868                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6869         else if (t->currentalpha < 1)
6870                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6871         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6872                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6873         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6874                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6875         if (t->backgroundnumskinframes)
6876                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6877         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6878         {
6879                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6880                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6881         }
6882         else
6883                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6884         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6885                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6886
6887         // there is no tcmod
6888         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6889         {
6890                 t->currenttexmatrix = r_waterscrollmatrix;
6891                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6892         }
6893         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6894         {
6895                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6896                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6897         }
6898
6899         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6900                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6901         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6902                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6903
6904         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6905         if (t->currentskinframe->qpixels)
6906                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6907         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6908         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
6909         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
6910         t->nmaptexture = t->currentskinframe->nmap;
6911         t->glosstexture = r_texture_black;
6912         t->glowtexture = t->currentskinframe->glow;
6913         t->fogtexture = t->currentskinframe->fog;
6914         if (t->backgroundnumskinframes)
6915         {
6916                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
6917                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
6918                 t->backgroundglosstexture = r_texture_black;
6919                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
6920         }
6921         else
6922         {
6923                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6924                 t->backgroundnmaptexture = r_texture_blanknormalmap;
6925                 t->backgroundglosstexture = r_texture_black;
6926                 t->backgroundglowtexture = NULL;
6927         }
6928         t->specularpower = r_shadow_glossexponent.value;
6929         // TODO: store reference values for these in the texture?
6930         t->specularscale = 0;
6931         if (r_shadow_gloss.integer > 0)
6932         {
6933                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6934                 {
6935                         if (r_shadow_glossintensity.value > 0)
6936                         {
6937                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6938                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6939                                 t->specularscale = r_shadow_glossintensity.value;
6940                         }
6941                 }
6942                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6943                 {
6944                         t->glosstexture = r_texture_white;
6945                         t->backgroundglosstexture = r_texture_white;
6946                         t->specularscale = r_shadow_gloss2intensity.value;
6947                         t->specularpower = r_shadow_gloss2exponent.value;
6948                 }
6949         }
6950         t->specularscale *= t->specularscalemod;
6951         t->specularpower *= t->specularpowermod;
6952
6953         // lightmaps mode looks bad with dlights using actual texturing, so turn
6954         // off the colormap and glossmap, but leave the normalmap on as it still
6955         // accurately represents the shading involved
6956         if (gl_lightmaps.integer)
6957         {
6958                 t->basetexture = r_texture_grey128;
6959                 t->pantstexture = r_texture_black;
6960                 t->shirttexture = r_texture_black;
6961                 t->nmaptexture = r_texture_blanknormalmap;
6962                 t->glosstexture = r_texture_black;
6963                 t->glowtexture = NULL;
6964                 t->fogtexture = NULL;
6965                 t->backgroundbasetexture = NULL;
6966                 t->backgroundnmaptexture = r_texture_blanknormalmap;
6967                 t->backgroundglosstexture = r_texture_black;
6968                 t->backgroundglowtexture = NULL;
6969                 t->specularscale = 0;
6970                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6971         }
6972
6973         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
6974         VectorClear(t->dlightcolor);
6975         t->currentnumlayers = 0;
6976         if (t->currentmaterialflags & MATERIALFLAG_WALL)
6977         {
6978                 int blendfunc1, blendfunc2;
6979                 qboolean depthmask;
6980                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6981                 {
6982                         blendfunc1 = GL_SRC_ALPHA;
6983                         blendfunc2 = GL_ONE;
6984                 }
6985                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6986                 {
6987                         blendfunc1 = GL_SRC_ALPHA;
6988                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6989                 }
6990                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6991                 {
6992                         blendfunc1 = t->customblendfunc[0];
6993                         blendfunc2 = t->customblendfunc[1];
6994                 }
6995                 else
6996                 {
6997                         blendfunc1 = GL_ONE;
6998                         blendfunc2 = GL_ZERO;
6999                 }
7000                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7001                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7002                 {
7003                         // fullbright is not affected by r_refdef.lightmapintensity
7004                         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]);
7005                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7006                                 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]);
7007                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7008                                 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]);
7009                 }
7010                 else
7011                 {
7012                         vec3_t ambientcolor;
7013                         float colorscale;
7014                         // set the color tint used for lights affecting this surface
7015                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7016                         colorscale = 2;
7017                         // q3bsp has no lightmap updates, so the lightstylevalue that
7018                         // would normally be baked into the lightmap must be
7019                         // applied to the color
7020                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7021                         if (model->type == mod_brushq3)
7022                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7023                         colorscale *= r_refdef.lightmapintensity;
7024                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7025                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7026                         // basic lit geometry
7027                         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]);
7028                         // add pants/shirt if needed
7029                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7030                                 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]);
7031                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7032                                 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]);
7033                         // now add ambient passes if needed
7034                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7035                         {
7036                                 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]);
7037                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7038                                         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]);
7039                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7040                                         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]);
7041                         }
7042                 }
7043                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7044                         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]);
7045                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7046                 {
7047                         // if this is opaque use alpha blend which will darken the earlier
7048                         // passes cheaply.
7049                         //
7050                         // if this is an alpha blended material, all the earlier passes
7051                         // were darkened by fog already, so we only need to add the fog
7052                         // color ontop through the fog mask texture
7053                         //
7054                         // if this is an additive blended material, all the earlier passes
7055                         // were darkened by fog already, and we should not add fog color
7056                         // (because the background was not darkened, there is no fog color
7057                         // that was lost behind it).
7058                         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]);
7059                 }
7060         }
7061
7062         return t->currentframe;
7063 }
7064
7065 rsurfacestate_t rsurface;
7066
7067 void R_Mesh_ResizeArrays(int newvertices)
7068 {
7069         float *base;
7070         if (rsurface.array_size >= newvertices)
7071                 return;
7072         if (rsurface.array_modelvertex3f)
7073                 Mem_Free(rsurface.array_modelvertex3f);
7074         rsurface.array_size = (newvertices + 1023) & ~1023;
7075         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
7076         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
7077         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
7078         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
7079         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
7080         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
7081         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
7082         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
7083         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
7084         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
7085         rsurface.array_color4f           = base + rsurface.array_size * 27;
7086         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
7087 }
7088
7089 void RSurf_ActiveWorldEntity(void)
7090 {
7091         dp_model_t *model = r_refdef.scene.worldmodel;
7092         //if (rsurface.entity == r_refdef.scene.worldentity)
7093         //      return;
7094         rsurface.entity = r_refdef.scene.worldentity;
7095         rsurface.skeleton = NULL;
7096         rsurface.ent_skinnum = 0;
7097         rsurface.ent_qwskin = -1;
7098         rsurface.ent_shadertime = 0;
7099         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7100         if (rsurface.array_size < model->surfmesh.num_vertices)
7101                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
7102         rsurface.matrix = identitymatrix;
7103         rsurface.inversematrix = identitymatrix;
7104         rsurface.matrixscale = 1;
7105         rsurface.inversematrixscale = 1;
7106         R_EntityMatrix(&identitymatrix);
7107         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7108         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7109         rsurface.fograngerecip = r_refdef.fograngerecip;
7110         rsurface.fogheightfade = r_refdef.fogheightfade;
7111         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7112         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7113         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7114         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7115         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7116         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7117         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7118         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7119         rsurface.colormod[3] = 1;
7120         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);
7121         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7122         rsurface.frameblend[0].lerp = 1;
7123         rsurface.ent_alttextures = false;
7124         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7125         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7126         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7127         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
7128         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7129         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7130         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
7131         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7132         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7133         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
7134         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7135         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7136         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
7137         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7138         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7139         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
7140         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7141         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7142         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
7143         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7144         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7145         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
7146         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7147         rsurface.modelelement3i = model->surfmesh.data_element3i;
7148         rsurface.modelelement3s = model->surfmesh.data_element3s;
7149         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
7150         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
7151         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7152         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
7153         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
7154         rsurface.modelsurfaces = model->data_surfaces;
7155         rsurface.generatedvertex = false;
7156         rsurface.vertex3f  = rsurface.modelvertex3f;
7157         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7158         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7159         rsurface.svector3f = rsurface.modelsvector3f;
7160         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7161         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7162         rsurface.tvector3f = rsurface.modeltvector3f;
7163         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7164         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7165         rsurface.normal3f  = rsurface.modelnormal3f;
7166         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7167         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7168         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7169 }
7170
7171 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7172 {
7173         dp_model_t *model = ent->model;
7174         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7175         //      return;
7176         rsurface.entity = (entity_render_t *)ent;
7177         rsurface.skeleton = ent->skeleton;
7178         rsurface.ent_skinnum = ent->skinnum;
7179         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;
7180         rsurface.ent_shadertime = ent->shadertime;
7181         rsurface.ent_flags = ent->flags;
7182         if (rsurface.array_size < model->surfmesh.num_vertices)
7183                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
7184         rsurface.matrix = ent->matrix;
7185         rsurface.inversematrix = ent->inversematrix;
7186         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7187         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7188         R_EntityMatrix(&rsurface.matrix);
7189         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7190         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7191         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7192         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7193         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7194         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7195         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7196         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7197         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7198         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7199         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7200         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7201         rsurface.colormod[3] = ent->alpha;
7202         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7203         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7204         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7205         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7206         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7207         if (ent->model->brush.submodel && !prepass)
7208         {
7209                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7210                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7211         }
7212         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7213         {
7214                 if (ent->animcache_vertex3f && !r_framedata_failed)
7215                 {
7216                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7217                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7218                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7219                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7220                 }
7221                 else if (wanttangents)
7222                 {
7223                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7224                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
7225                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
7226                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7227                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
7228                 }
7229                 else if (wantnormals)
7230                 {
7231                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7232                         rsurface.modelsvector3f = NULL;
7233                         rsurface.modeltvector3f = NULL;
7234                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7235                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
7236                 }
7237                 else
7238                 {
7239                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7240                         rsurface.modelsvector3f = NULL;
7241                         rsurface.modeltvector3f = NULL;
7242                         rsurface.modelnormal3f = NULL;
7243                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
7244                 }
7245                 rsurface.modelvertex3f_bufferobject = 0;
7246                 rsurface.modelvertex3f_bufferoffset = 0;
7247                 rsurface.modelsvector3f_bufferobject = 0;
7248                 rsurface.modelsvector3f_bufferoffset = 0;
7249                 rsurface.modeltvector3f_bufferobject = 0;
7250                 rsurface.modeltvector3f_bufferoffset = 0;
7251                 rsurface.modelnormal3f_bufferobject = 0;
7252                 rsurface.modelnormal3f_bufferoffset = 0;
7253                 rsurface.generatedvertex = true;
7254         }
7255         else
7256         {
7257                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7258                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
7259                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7260                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7261                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
7262                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7263                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7264                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
7265                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7266                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7267                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
7268                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7269                 rsurface.generatedvertex = false;
7270         }
7271         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7272         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
7273         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7274         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7275         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
7276         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7277         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7278         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
7279         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7280         rsurface.modelelement3i = model->surfmesh.data_element3i;
7281         rsurface.modelelement3s = model->surfmesh.data_element3s;
7282         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
7283         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
7284         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7285         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
7286         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
7287         rsurface.modelsurfaces = model->data_surfaces;
7288         rsurface.vertex3f  = rsurface.modelvertex3f;
7289         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7290         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7291         rsurface.svector3f = rsurface.modelsvector3f;
7292         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7293         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7294         rsurface.tvector3f = rsurface.modeltvector3f;
7295         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7296         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7297         rsurface.normal3f  = rsurface.modelnormal3f;
7298         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7299         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7300         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7301 }
7302
7303 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)
7304 {
7305         rsurface.entity = r_refdef.scene.worldentity;
7306         rsurface.skeleton = NULL;
7307         rsurface.ent_skinnum = 0;
7308         rsurface.ent_qwskin = -1;
7309         rsurface.ent_shadertime = shadertime;
7310         rsurface.ent_flags = entflags;
7311         rsurface.modelnum_vertices = numvertices;
7312         rsurface.modelnum_triangles = numtriangles;
7313         if (rsurface.array_size < rsurface.modelnum_vertices)
7314                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
7315         rsurface.matrix = *matrix;
7316         rsurface.inversematrix = *inversematrix;
7317         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7318         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7319         R_EntityMatrix(&rsurface.matrix);
7320         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7321         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7322         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7323         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7324         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7325         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7326         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7327         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7328         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7329         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7330         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7331         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7332         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);
7333         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7334         rsurface.frameblend[0].lerp = 1;
7335         rsurface.ent_alttextures = false;
7336         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7337         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7338         if (wanttangents)
7339         {
7340                 rsurface.modelvertex3f = vertex3f;
7341                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
7342                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
7343                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
7344         }
7345         else if (wantnormals)
7346         {
7347                 rsurface.modelvertex3f = vertex3f;
7348                 rsurface.modelsvector3f = NULL;
7349                 rsurface.modeltvector3f = NULL;
7350                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
7351         }
7352         else
7353         {
7354                 rsurface.modelvertex3f = vertex3f;
7355                 rsurface.modelsvector3f = NULL;
7356                 rsurface.modeltvector3f = NULL;
7357                 rsurface.modelnormal3f = NULL;
7358         }
7359         rsurface.modelvertex3f_bufferobject = 0;
7360         rsurface.modelvertex3f_bufferoffset = 0;
7361         rsurface.modelsvector3f_bufferobject = 0;
7362         rsurface.modelsvector3f_bufferoffset = 0;
7363         rsurface.modeltvector3f_bufferobject = 0;
7364         rsurface.modeltvector3f_bufferoffset = 0;
7365         rsurface.modelnormal3f_bufferobject = 0;
7366         rsurface.modelnormal3f_bufferoffset = 0;
7367         rsurface.generatedvertex = true;
7368         rsurface.modellightmapcolor4f  = color4f;
7369         rsurface.modellightmapcolor4f_bufferobject = 0;
7370         rsurface.modellightmapcolor4f_bufferoffset = 0;
7371         rsurface.modeltexcoordtexture2f  = texcoord2f;
7372         rsurface.modeltexcoordtexture2f_bufferobject = 0;
7373         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7374         rsurface.modeltexcoordlightmap2f  = NULL;
7375         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
7376         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7377         rsurface.modelelement3i = element3i;
7378         rsurface.modelelement3s = element3s;
7379         rsurface.modelelement3i_bufferobject = 0;
7380         rsurface.modelelement3s_bufferobject = 0;
7381         rsurface.modellightmapoffsets = NULL;
7382         rsurface.modelsurfaces = NULL;
7383         rsurface.vertex3f  = rsurface.modelvertex3f;
7384         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7385         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7386         rsurface.svector3f = rsurface.modelsvector3f;
7387         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7388         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7389         rsurface.tvector3f = rsurface.modeltvector3f;
7390         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7391         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7392         rsurface.normal3f  = rsurface.modelnormal3f;
7393         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7394         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7395         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7396
7397         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
7398         {
7399                 if ((wantnormals || wanttangents) && !normal3f)
7400                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7401                 if (wanttangents && !svector3f)
7402                         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);
7403         }
7404 }
7405
7406 float RSurf_FogPoint(const float *v)
7407 {
7408         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7409         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7410         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7411         float FogHeightFade = r_refdef.fogheightfade;
7412         float fogfrac;
7413         unsigned int fogmasktableindex;
7414         if (r_refdef.fogplaneviewabove)
7415                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7416         else
7417                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7418         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7419         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7420 }
7421
7422 float RSurf_FogVertex(const float *v)
7423 {
7424         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7425         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7426         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7427         float FogHeightFade = rsurface.fogheightfade;
7428         float fogfrac;
7429         unsigned int fogmasktableindex;
7430         if (r_refdef.fogplaneviewabove)
7431                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7432         else
7433                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7434         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7435         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7436 }
7437
7438 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
7439 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
7440 {
7441         int deformindex;
7442         int texturesurfaceindex;
7443         int i, j;
7444         float amplitude;
7445         float animpos;
7446         float scale;
7447         const float *v1, *in_tc;
7448         float *out_tc;
7449         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
7450         float waveparms[4];
7451         q3shaderinfo_deform_t *deform;
7452         // 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
7453         if (rsurface.generatedvertex)
7454         {
7455                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
7456                         generatenormals = true;
7457                 for (i = 0;i < Q3MAXDEFORMS;i++)
7458                 {
7459                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
7460                         {
7461                                 generatetangents = true;
7462                                 generatenormals = true;
7463                         }
7464                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
7465                                 generatenormals = true;
7466                 }
7467                 if (generatenormals && !rsurface.modelnormal3f)
7468                 {
7469                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7470                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
7471                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
7472                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7473                 }
7474                 if (generatetangents && !rsurface.modelsvector3f)
7475                 {
7476                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
7477                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
7478                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
7479                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
7480                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
7481                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
7482                         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);
7483                 }
7484         }
7485         rsurface.vertex3f  = rsurface.modelvertex3f;
7486         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7487         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7488         rsurface.svector3f = rsurface.modelsvector3f;
7489         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7490         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7491         rsurface.tvector3f = rsurface.modeltvector3f;
7492         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7493         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7494         rsurface.normal3f  = rsurface.modelnormal3f;
7495         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7496         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7497         // if vertices are deformed (sprite flares and things in maps, possibly
7498         // water waves, bulges and other deformations), generate them into
7499         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
7500         // (may be static model data or generated data for an animated model, or
7501         //  the previous deform pass)
7502         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
7503         {
7504                 switch (deform->deform)
7505                 {
7506                 default:
7507                 case Q3DEFORM_PROJECTIONSHADOW:
7508                 case Q3DEFORM_TEXT0:
7509                 case Q3DEFORM_TEXT1:
7510                 case Q3DEFORM_TEXT2:
7511                 case Q3DEFORM_TEXT3:
7512                 case Q3DEFORM_TEXT4:
7513                 case Q3DEFORM_TEXT5:
7514                 case Q3DEFORM_TEXT6:
7515                 case Q3DEFORM_TEXT7:
7516                 case Q3DEFORM_NONE:
7517                         break;
7518                 case Q3DEFORM_AUTOSPRITE:
7519                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
7520                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
7521                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
7522                         VectorNormalize(newforward);
7523                         VectorNormalize(newright);
7524                         VectorNormalize(newup);
7525                         // make deformed versions of only the model vertices used by the specified surfaces
7526                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7527                         {
7528                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7529                                 // a single autosprite surface can contain multiple sprites...
7530                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
7531                                 {
7532                                         VectorClear(center);
7533                                         for (i = 0;i < 4;i++)
7534                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
7535                                         VectorScale(center, 0.25f, center);
7536                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
7537                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
7538                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
7539                                         for (i = 0;i < 4;i++)
7540                                         {
7541                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
7542                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
7543                                         }
7544                                 }
7545                                 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);
7546                                 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);
7547                         }
7548                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7549                         rsurface.vertex3f_bufferobject = 0;
7550                         rsurface.vertex3f_bufferoffset = 0;
7551                         rsurface.svector3f = rsurface.array_deformedsvector3f;
7552                         rsurface.svector3f_bufferobject = 0;
7553                         rsurface.svector3f_bufferoffset = 0;
7554                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
7555                         rsurface.tvector3f_bufferobject = 0;
7556                         rsurface.tvector3f_bufferoffset = 0;
7557                         rsurface.normal3f = rsurface.array_deformednormal3f;
7558                         rsurface.normal3f_bufferobject = 0;
7559                         rsurface.normal3f_bufferoffset = 0;
7560                         break;
7561                 case Q3DEFORM_AUTOSPRITE2:
7562                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
7563                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
7564                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
7565                         VectorNormalize(newforward);
7566                         VectorNormalize(newright);
7567                         VectorNormalize(newup);
7568                         // make deformed versions of only the model vertices used by the specified surfaces
7569                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7570                         {
7571                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7572                                 const float *v1, *v2;
7573                                 vec3_t start, end;
7574                                 float f, l;
7575                                 struct
7576                                 {
7577                                         float length2;
7578                                         const float *v1;
7579                                         const float *v2;
7580                                 }
7581                                 shortest[2];
7582                                 memset(shortest, 0, sizeof(shortest));
7583                                 // a single autosprite surface can contain multiple sprites...
7584                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
7585                                 {
7586                                         VectorClear(center);
7587                                         for (i = 0;i < 4;i++)
7588                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
7589                                         VectorScale(center, 0.25f, center);
7590                                         // find the two shortest edges, then use them to define the
7591                                         // axis vectors for rotating around the central axis
7592                                         for (i = 0;i < 6;i++)
7593                                         {
7594                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
7595                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
7596 #if 0
7597                                                 Debug_PolygonBegin(NULL, 0);
7598                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
7599                                                 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);
7600                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
7601                                                 Debug_PolygonEnd();
7602 #endif
7603                                                 l = VectorDistance2(v1, v2);
7604                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
7605                                                 if (v1[2] != v2[2])
7606                                                         l += (1.0f / 1024.0f);
7607                                                 if (shortest[0].length2 > l || i == 0)
7608                                                 {
7609                                                         shortest[1] = shortest[0];
7610                                                         shortest[0].length2 = l;
7611                                                         shortest[0].v1 = v1;
7612                                                         shortest[0].v2 = v2;
7613                                                 }
7614                                                 else if (shortest[1].length2 > l || i == 1)
7615                                                 {
7616                                                         shortest[1].length2 = l;
7617                                                         shortest[1].v1 = v1;
7618                                                         shortest[1].v2 = v2;
7619                                                 }
7620                                         }
7621                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
7622                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
7623 #if 0
7624                                         Debug_PolygonBegin(NULL, 0);
7625                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
7626                                         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);
7627                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
7628                                         Debug_PolygonEnd();
7629 #endif
7630                                         // this calculates the right vector from the shortest edge
7631                                         // and the up vector from the edge midpoints
7632                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
7633                                         VectorNormalize(right);
7634                                         VectorSubtract(end, start, up);
7635                                         VectorNormalize(up);
7636                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
7637                                         VectorSubtract(rsurface.localvieworigin, center, forward);
7638                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
7639                                         VectorNegate(forward, forward);
7640                                         VectorReflect(forward, 0, up, forward);
7641                                         VectorNormalize(forward);
7642                                         CrossProduct(up, forward, newright);
7643                                         VectorNormalize(newright);
7644 #if 0
7645                                         Debug_PolygonBegin(NULL, 0);
7646                                         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);
7647                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
7648                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
7649                                         Debug_PolygonEnd();
7650 #endif
7651 #if 0
7652                                         Debug_PolygonBegin(NULL, 0);
7653                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
7654                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
7655                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
7656                                         Debug_PolygonEnd();
7657 #endif
7658                                         // rotate the quad around the up axis vector, this is made
7659                                         // especially easy by the fact we know the quad is flat,
7660                                         // so we only have to subtract the center position and
7661                                         // measure distance along the right vector, and then
7662                                         // multiply that by the newright vector and add back the
7663                                         // center position
7664                                         // we also need to subtract the old position to undo the
7665                                         // displacement from the center, which we do with a
7666                                         // DotProduct, the subtraction/addition of center is also
7667                                         // optimized into DotProducts here
7668                                         l = DotProduct(right, center);
7669                                         for (i = 0;i < 4;i++)
7670                                         {
7671                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
7672                                                 f = DotProduct(right, v1) - l;
7673                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
7674                                         }
7675                                 }
7676                                 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);
7677                                 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);
7678                         }
7679                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7680                         rsurface.vertex3f_bufferobject = 0;
7681                         rsurface.vertex3f_bufferoffset = 0;
7682                         rsurface.svector3f = rsurface.array_deformedsvector3f;
7683                         rsurface.svector3f_bufferobject = 0;
7684                         rsurface.svector3f_bufferoffset = 0;
7685                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
7686                         rsurface.tvector3f_bufferobject = 0;
7687                         rsurface.tvector3f_bufferoffset = 0;
7688                         rsurface.normal3f = rsurface.array_deformednormal3f;
7689                         rsurface.normal3f_bufferobject = 0;
7690                         rsurface.normal3f_bufferoffset = 0;
7691                         break;
7692                 case Q3DEFORM_NORMAL:
7693                         // deform the normals to make reflections wavey
7694                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7695                         {
7696                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7697                                 for (j = 0;j < surface->num_vertices;j++)
7698                                 {
7699                                         float vertex[3];
7700                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
7701                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
7702                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
7703                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7704                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7705                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7706                                         VectorNormalize(normal);
7707                                 }
7708                                 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);
7709                         }
7710                         rsurface.svector3f = rsurface.array_deformedsvector3f;
7711                         rsurface.svector3f_bufferobject = 0;
7712                         rsurface.svector3f_bufferoffset = 0;
7713                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
7714                         rsurface.tvector3f_bufferobject = 0;
7715                         rsurface.tvector3f_bufferoffset = 0;
7716                         rsurface.normal3f = rsurface.array_deformednormal3f;
7717                         rsurface.normal3f_bufferobject = 0;
7718                         rsurface.normal3f_bufferoffset = 0;
7719                         break;
7720                 case Q3DEFORM_WAVE:
7721                         // deform vertex array to make wavey water and flags and such
7722                         waveparms[0] = deform->waveparms[0];
7723                         waveparms[1] = deform->waveparms[1];
7724                         waveparms[2] = deform->waveparms[2];
7725                         waveparms[3] = deform->waveparms[3];
7726                         // this is how a divisor of vertex influence on deformation
7727                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
7728                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
7729                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7730                         {
7731                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7732                                 for (j = 0;j < surface->num_vertices;j++)
7733                                 {
7734                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
7735                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
7736                                         // if the wavefunc depends on time, evaluate it per-vertex
7737                                         if (waveparms[3])
7738                                         {
7739                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
7740                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
7741                                         }
7742                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
7743                                 }
7744                         }
7745                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7746                         rsurface.vertex3f_bufferobject = 0;
7747                         rsurface.vertex3f_bufferoffset = 0;
7748                         break;
7749                 case Q3DEFORM_BULGE:
7750                         // deform vertex array to make the surface have moving bulges
7751                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7752                         {
7753                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7754                                 for (j = 0;j < surface->num_vertices;j++)
7755                                 {
7756                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
7757                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
7758                                 }
7759                         }
7760                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7761                         rsurface.vertex3f_bufferobject = 0;
7762                         rsurface.vertex3f_bufferoffset = 0;
7763                         break;
7764                 case Q3DEFORM_MOVE:
7765                         // deform vertex array
7766                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
7767                         VectorScale(deform->parms, scale, waveparms);
7768                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7769                         {
7770                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7771                                 for (j = 0;j < surface->num_vertices;j++)
7772                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
7773                         }
7774                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7775                         rsurface.vertex3f_bufferobject = 0;
7776                         rsurface.vertex3f_bufferoffset = 0;
7777                         break;
7778                 }
7779         }
7780         // generate texcoords based on the chosen texcoord source
7781         switch(rsurface.texture->tcgen.tcgen)
7782         {
7783         default:
7784         case Q3TCGEN_TEXTURE:
7785                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
7786                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
7787                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
7788                 break;
7789         case Q3TCGEN_LIGHTMAP:
7790                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
7791                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
7792                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
7793                 break;
7794         case Q3TCGEN_VECTOR:
7795                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7796                 {
7797                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7798                         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)
7799                         {
7800                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
7801                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
7802                         }
7803                 }
7804                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7805                 rsurface.texcoordtexture2f_bufferobject  = 0;
7806                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7807                 break;
7808         case Q3TCGEN_ENVIRONMENT:
7809                 // make environment reflections using a spheremap
7810                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7811                 {
7812                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7813                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
7814                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
7815                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
7816                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
7817                         {
7818                                 // identical to Q3A's method, but executed in worldspace so
7819                                 // carried models can be shiny too
7820
7821                                 float viewer[3], d, reflected[3], worldreflected[3];
7822
7823                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
7824                                 // VectorNormalize(viewer);
7825
7826                                 d = DotProduct(normal, viewer);
7827
7828                                 reflected[0] = normal[0]*2*d - viewer[0];
7829                                 reflected[1] = normal[1]*2*d - viewer[1];
7830                                 reflected[2] = normal[2]*2*d - viewer[2];
7831                                 // note: this is proportinal to viewer, so we can normalize later
7832
7833                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7834                                 VectorNormalize(worldreflected);
7835
7836                                 // note: this sphere map only uses world x and z!
7837                                 // so positive and negative y will LOOK THE SAME.
7838                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7839                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7840                         }
7841                 }
7842                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7843                 rsurface.texcoordtexture2f_bufferobject  = 0;
7844                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7845                 break;
7846         }
7847         // the only tcmod that needs software vertex processing is turbulent, so
7848         // check for it here and apply the changes if needed
7849         // and we only support that as the first one
7850         // (handling a mixture of turbulent and other tcmods would be problematic
7851         //  without punting it entirely to a software path)
7852         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7853         {
7854                 amplitude = rsurface.texture->tcmods[0].parms[1];
7855                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7856                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7857                 {
7858                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7859                         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)
7860                         {
7861                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7862                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7863                         }
7864                 }
7865                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7866                 rsurface.texcoordtexture2f_bufferobject  = 0;
7867                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7868         }
7869         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
7870         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7871         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7872         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7873 }
7874
7875 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7876 {
7877         int i, j;
7878         const msurface_t *surface = texturesurfacelist[0];
7879         const msurface_t *surface2;
7880         int firstvertex;
7881         int endvertex;
7882         int numvertices;
7883         int numtriangles;
7884         // TODO: lock all array ranges before render, rather than on each surface
7885         if (texturenumsurfaces == 1)
7886         {
7887                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7888                 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);
7889         }
7890         else if (r_batchmode.integer == 2)
7891         {
7892                 #define MAXBATCHTRIANGLES 4096
7893                 int batchtriangles = 0;
7894                 static int batchelements[MAXBATCHTRIANGLES*3];
7895                 for (i = 0;i < texturenumsurfaces;i = j)
7896                 {
7897                         surface = texturesurfacelist[i];
7898                         j = i + 1;
7899                         if (surface->num_triangles > MAXBATCHTRIANGLES)
7900                         {
7901                                 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);
7902                                 continue;
7903                         }
7904                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7905                         batchtriangles = surface->num_triangles;
7906                         firstvertex = surface->num_firstvertex;
7907                         endvertex = surface->num_firstvertex + surface->num_vertices;
7908                         for (;j < texturenumsurfaces;j++)
7909                         {
7910                                 surface2 = texturesurfacelist[j];
7911                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7912                                         break;
7913                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7914                                 batchtriangles += surface2->num_triangles;
7915                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
7916                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7917                         }
7918                         surface2 = texturesurfacelist[j-1];
7919                         numvertices = endvertex - firstvertex;
7920                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7921                 }
7922         }
7923         else if (r_batchmode.integer == 1)
7924         {
7925                 for (i = 0;i < texturenumsurfaces;i = j)
7926                 {
7927                         surface = texturesurfacelist[i];
7928                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7929                                 if (texturesurfacelist[j] != surface2)
7930                                         break;
7931                         surface2 = texturesurfacelist[j-1];
7932                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7933                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7934                         GL_LockArrays(surface->num_firstvertex, numvertices);
7935                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7936                 }
7937         }
7938         else
7939         {
7940                 for (i = 0;i < texturenumsurfaces;i++)
7941                 {
7942                         surface = texturesurfacelist[i];
7943                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7944                         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);
7945                 }
7946         }
7947 }
7948
7949 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
7950 {
7951         switch(vid.renderpath)
7952         {
7953         case RENDERPATH_CGGL:
7954 #ifdef SUPPORTCG
7955                 if (r_cg_permutation->fp_Texture_Lightmap ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Lightmap , R_GetTexture(surface->lightmaptexture ));
7956                 if (r_cg_permutation->fp_Texture_Deluxemap) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Deluxemap, R_GetTexture(surface->deluxemaptexture));
7957 #endif
7958                 break;
7959         case RENDERPATH_GL20:
7960                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(surface->lightmaptexture ));
7961                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, R_GetTexture(surface->deluxemaptexture));
7962                 break;
7963         case RENDERPATH_GL13:
7964         case RENDERPATH_GL11:
7965                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
7966                 break;
7967         }
7968 }
7969
7970 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
7971 {
7972         // pick the closest matching water plane and bind textures
7973         int planeindex, vertexindex;
7974         float d, bestd;
7975         vec3_t vert;
7976         const float *v;
7977         r_waterstate_waterplane_t *p, *bestp;
7978         bestd = 0;
7979         bestp = NULL;
7980         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7981         {
7982                 d = 0;
7983                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7984                 {
7985                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
7986                         d += fabs(PlaneDiff(vert, &p->plane));
7987                 }
7988                 if (bestd > d || !bestp)
7989                 {
7990                         bestd = d;
7991                         bestp = p;
7992                 }
7993         }
7994         switch(vid.renderpath)
7995         {
7996         case RENDERPATH_CGGL:
7997 #ifdef SUPPORTCG
7998                 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));
7999                 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));
8000 #endif
8001                 break;
8002         case RENDERPATH_GL20:
8003                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));
8004                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));
8005                 break;
8006         case RENDERPATH_GL13:
8007         case RENDERPATH_GL11:
8008                 break;
8009         }
8010 }
8011
8012 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8013 {
8014         int i;
8015         const msurface_t *surface;
8016         if (r_waterstate.renderingscene)
8017                 return;
8018         for (i = 0;i < texturenumsurfaces;i++)
8019         {
8020                 surface = texturesurfacelist[i];
8021                 RSurf_BindLightmapForSurface(surface);
8022                 RSurf_BindReflectionForSurface(surface);
8023                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8024                 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);
8025         }
8026 }
8027
8028 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8029 {
8030         int i;
8031         int j;
8032         const msurface_t *surface = texturesurfacelist[0];
8033         const msurface_t *surface2;
8034         int firstvertex;
8035         int endvertex;
8036         int numvertices;
8037         int numtriangles;
8038         if (texturenumsurfaces == 1)
8039         {
8040                 RSurf_BindLightmapForSurface(surface);
8041                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8042                 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);
8043         }
8044         else if (r_batchmode.integer == 2)
8045         {
8046 #define MAXBATCHTRIANGLES 4096
8047                 int batchtriangles = 0;
8048                 static int batchelements[MAXBATCHTRIANGLES*3];
8049                 for (i = 0;i < texturenumsurfaces;i = j)
8050                 {
8051                         surface = texturesurfacelist[i];
8052                         RSurf_BindLightmapForSurface(surface);
8053                         j = i + 1;
8054                         if (surface->num_triangles > MAXBATCHTRIANGLES)
8055                         {
8056                                 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);
8057                                 continue;
8058                         }
8059                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
8060                         batchtriangles = surface->num_triangles;
8061                         firstvertex = surface->num_firstvertex;
8062                         endvertex = surface->num_firstvertex + surface->num_vertices;
8063                         for (;j < texturenumsurfaces;j++)
8064                         {
8065                                 surface2 = texturesurfacelist[j];
8066                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
8067                                         break;
8068                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
8069                                 batchtriangles += surface2->num_triangles;
8070                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
8071                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
8072                         }
8073                         surface2 = texturesurfacelist[j-1];
8074                         numvertices = endvertex - firstvertex;
8075                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
8076                 }
8077         }
8078         else if (r_batchmode.integer == 1)
8079         {
8080 #if 0
8081                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
8082                 for (i = 0;i < texturenumsurfaces;i = j)
8083                 {
8084                         surface = texturesurfacelist[i];
8085                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
8086                                 if (texturesurfacelist[j] != surface2)
8087                                         break;
8088                         Con_Printf(" %i", j - i);
8089                 }
8090                 Con_Printf("\n");
8091                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
8092 #endif
8093                 for (i = 0;i < texturenumsurfaces;i = j)
8094                 {
8095                         surface = texturesurfacelist[i];
8096                         RSurf_BindLightmapForSurface(surface);
8097                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
8098                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
8099                                         break;
8100 #if 0
8101                         Con_Printf(" %i", j - i);
8102 #endif
8103                         surface2 = texturesurfacelist[j-1];
8104                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
8105                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
8106                         GL_LockArrays(surface->num_firstvertex, numvertices);
8107                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
8108                 }
8109 #if 0
8110                 Con_Printf("\n");
8111 #endif
8112         }
8113         else
8114         {
8115                 for (i = 0;i < texturenumsurfaces;i++)
8116                 {
8117                         surface = texturesurfacelist[i];
8118                         RSurf_BindLightmapForSurface(surface);
8119                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8120                         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);
8121                 }
8122         }
8123 }
8124
8125 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8126 {
8127         int j;
8128         int texturesurfaceindex;
8129         if (r_showsurfaces.integer == 2)
8130         {
8131                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8132                 {
8133                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8134                         for (j = 0;j < surface->num_triangles;j++)
8135                         {
8136                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
8137                                 GL_Color(f, f, f, 1);
8138                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
8139                         }
8140                 }
8141         }
8142         else
8143         {
8144                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8145                 {
8146                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8147                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
8148                         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);
8149                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8150                         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);
8151                 }
8152         }
8153 }
8154
8155 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8156 {
8157         int texturesurfaceindex;
8158         int i;
8159         const float *v;
8160         float *c2;
8161         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8162         {
8163                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8164                 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)
8165                 {
8166                         c2[0] = 0.5;
8167                         c2[1] = 0.5;
8168                         c2[2] = 0.5;
8169                         c2[3] = 1;
8170                 }
8171         }
8172         rsurface.lightmapcolor4f = rsurface.array_color4f;
8173         rsurface.lightmapcolor4f_bufferobject = 0;
8174         rsurface.lightmapcolor4f_bufferoffset = 0;
8175 }
8176
8177 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8178 {
8179         int texturesurfaceindex;
8180         int i;
8181         float f;
8182         const float *v;
8183         const float *c;
8184         float *c2;
8185         if (rsurface.lightmapcolor4f)
8186         {
8187                 // generate color arrays for the surfaces in this list
8188                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8189                 {
8190                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8191                         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)
8192                         {
8193                                 f = RSurf_FogVertex(v);
8194                                 c2[0] = c[0] * f;
8195                                 c2[1] = c[1] * f;
8196                                 c2[2] = c[2] * f;
8197                                 c2[3] = c[3];
8198                         }
8199                 }
8200         }
8201         else
8202         {
8203                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8204                 {
8205                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8206                         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)
8207                         {
8208                                 f = RSurf_FogVertex(v);
8209                                 c2[0] = f;
8210                                 c2[1] = f;
8211                                 c2[2] = f;
8212                                 c2[3] = 1;
8213                         }
8214                 }
8215         }
8216         rsurface.lightmapcolor4f = rsurface.array_color4f;
8217         rsurface.lightmapcolor4f_bufferobject = 0;
8218         rsurface.lightmapcolor4f_bufferoffset = 0;
8219 }
8220
8221 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8222 {
8223         int texturesurfaceindex;
8224         int i;
8225         float f;
8226         const float *v;
8227         const float *c;
8228         float *c2;
8229         if (!rsurface.lightmapcolor4f)
8230                 return;
8231         // generate color arrays for the surfaces in this list
8232         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8233         {
8234                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8235                 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)
8236                 {
8237                         f = RSurf_FogVertex(v);
8238                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8239                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8240                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8241                         c2[3] = c[3];
8242                 }
8243         }
8244         rsurface.lightmapcolor4f = rsurface.array_color4f;
8245         rsurface.lightmapcolor4f_bufferobject = 0;
8246         rsurface.lightmapcolor4f_bufferoffset = 0;
8247 }
8248
8249 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
8250 {
8251         int texturesurfaceindex;
8252         int i;
8253         const float *c;
8254         float *c2;
8255         if (!rsurface.lightmapcolor4f)
8256                 return;
8257         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8258         {
8259                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8260                 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)
8261                 {
8262                         c2[0] = c[0] * r;
8263                         c2[1] = c[1] * g;
8264                         c2[2] = c[2] * b;
8265                         c2[3] = c[3] * a;
8266                 }
8267         }
8268         rsurface.lightmapcolor4f = rsurface.array_color4f;
8269         rsurface.lightmapcolor4f_bufferobject = 0;
8270         rsurface.lightmapcolor4f_bufferoffset = 0;
8271 }
8272
8273 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8274 {
8275         int texturesurfaceindex;
8276         int i;
8277         const float *c;
8278         float *c2;
8279         if (!rsurface.lightmapcolor4f)
8280                 return;
8281         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8282         {
8283                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8284                 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)
8285                 {
8286                         c2[0] = c[0] + r_refdef.scene.ambient;
8287                         c2[1] = c[1] + r_refdef.scene.ambient;
8288                         c2[2] = c[2] + r_refdef.scene.ambient;
8289                         c2[3] = c[3];
8290                 }
8291         }
8292         rsurface.lightmapcolor4f = rsurface.array_color4f;
8293         rsurface.lightmapcolor4f_bufferobject = 0;
8294         rsurface.lightmapcolor4f_bufferoffset = 0;
8295 }
8296
8297 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8298 {
8299         // TODO: optimize
8300         rsurface.lightmapcolor4f = NULL;
8301         rsurface.lightmapcolor4f_bufferobject = 0;
8302         rsurface.lightmapcolor4f_bufferoffset = 0;
8303         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8304         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8305         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8306         GL_Color(r, g, b, a);
8307         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
8308 }
8309
8310 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8311 {
8312         // TODO: optimize applyfog && applycolor case
8313         // just apply fog if necessary, and tint the fog color array if necessary
8314         rsurface.lightmapcolor4f = NULL;
8315         rsurface.lightmapcolor4f_bufferobject = 0;
8316         rsurface.lightmapcolor4f_bufferoffset = 0;
8317         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8318         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8319         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8320         GL_Color(r, g, b, a);
8321         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8322 }
8323
8324 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8325 {
8326         int texturesurfaceindex;
8327         int i;
8328         float *c;
8329         // TODO: optimize
8330         if (texturesurfacelist[0]->lightmapinfo)
8331         {
8332                 // generate color arrays for the surfaces in this list
8333                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8334                 {
8335                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8336                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
8337                         {
8338                                 if (surface->lightmapinfo->samples)
8339                                 {
8340                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
8341                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
8342                                         VectorScale(lm, scale, c);
8343                                         if (surface->lightmapinfo->styles[1] != 255)
8344                                         {
8345                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8346                                                 lm += size3;
8347                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
8348                                                 VectorMA(c, scale, lm, c);
8349                                                 if (surface->lightmapinfo->styles[2] != 255)
8350                                                 {
8351                                                         lm += size3;
8352                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
8353                                                         VectorMA(c, scale, lm, c);
8354                                                         if (surface->lightmapinfo->styles[3] != 255)
8355                                                         {
8356                                                                 lm += size3;
8357                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
8358                                                                 VectorMA(c, scale, lm, c);
8359                                                         }
8360                                                 }
8361                                         }
8362                                 }
8363                                 else
8364                                         VectorClear(c);
8365                                 c[3] = 1;
8366                         }
8367                 }
8368                 rsurface.lightmapcolor4f = rsurface.array_color4f;
8369                 rsurface.lightmapcolor4f_bufferobject = 0;
8370                 rsurface.lightmapcolor4f_bufferoffset = 0;
8371         }
8372         else
8373         {
8374                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8375                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8376                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8377         }
8378         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8379         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8380         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8381         GL_Color(r, g, b, a);
8382         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8383 }
8384
8385 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
8386 {
8387         int texturesurfaceindex;
8388         int i;
8389         float f;
8390         float alpha;
8391         const float *v;
8392         const float *n;
8393         float *c;
8394         vec3_t ambientcolor;
8395         vec3_t diffusecolor;
8396         vec3_t lightdir;
8397         // TODO: optimize
8398         // model lighting
8399         VectorCopy(rsurface.modellight_lightdir, lightdir);
8400         f = 0.5f * r_refdef.lightmapintensity;
8401         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
8402         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
8403         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
8404         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
8405         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
8406         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
8407         alpha = *a;
8408         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
8409         {
8410                 // generate color arrays for the surfaces in this list
8411                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8412                 {
8413                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8414                         int numverts = surface->num_vertices;
8415                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
8416                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
8417                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
8418                         // q3-style directional shading
8419                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
8420                         {
8421                                 if ((f = DotProduct(n, lightdir)) > 0)
8422                                         VectorMA(ambientcolor, f, diffusecolor, c);
8423                                 else
8424                                         VectorCopy(ambientcolor, c);
8425                                 c[3] = alpha;
8426                         }
8427                 }
8428                 *r = 1;
8429                 *g = 1;
8430                 *b = 1;
8431                 *a = 1;
8432                 rsurface.lightmapcolor4f = rsurface.array_color4f;
8433                 rsurface.lightmapcolor4f_bufferobject = 0;
8434                 rsurface.lightmapcolor4f_bufferoffset = 0;
8435                 *applycolor = false;
8436         }
8437         else
8438         {
8439                 *r = ambientcolor[0];
8440                 *g = ambientcolor[1];
8441                 *b = ambientcolor[2];
8442                 rsurface.lightmapcolor4f = NULL;
8443                 rsurface.lightmapcolor4f_bufferobject = 0;
8444                 rsurface.lightmapcolor4f_bufferoffset = 0;
8445         }
8446 }
8447
8448 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8449 {
8450         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
8451         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8452         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8453         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8454         GL_Color(r, g, b, a);
8455         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8456 }
8457
8458 void RSurf_SetupDepthAndCulling(void)
8459 {
8460         // submodels are biased to avoid z-fighting with world surfaces that they
8461         // may be exactly overlapping (avoids z-fighting artifacts on certain
8462         // doors and things in Quake maps)
8463         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
8464         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
8465         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
8466         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
8467 }
8468
8469 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8470 {
8471         // transparent sky would be ridiculous
8472         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8473                 return;
8474         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8475         skyrenderlater = true;
8476         RSurf_SetupDepthAndCulling();
8477         GL_DepthMask(true);
8478         // LordHavoc: HalfLife maps have freaky skypolys so don't use
8479         // skymasking on them, and Quake3 never did sky masking (unlike
8480         // software Quake and software Quake2), so disable the sky masking
8481         // in Quake3 maps as it causes problems with q3map2 sky tricks,
8482         // and skymasking also looks very bad when noclipping outside the
8483         // level, so don't use it then either.
8484         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
8485         {
8486                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
8487                 R_Mesh_ColorPointer(NULL, 0, 0);
8488                 R_Mesh_ResetTextureState();
8489                 if (skyrendermasked)
8490                 {
8491                         R_SetupShader_DepthOrShadow();
8492                         // depth-only (masking)
8493                         GL_ColorMask(0,0,0,0);
8494                         // just to make sure that braindead drivers don't draw
8495                         // anything despite that colormask...
8496                         GL_BlendFunc(GL_ZERO, GL_ONE);
8497                 }
8498                 else
8499                 {
8500                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8501                         // fog sky
8502                         GL_BlendFunc(GL_ONE, GL_ZERO);
8503                 }
8504                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8505                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8506                 if (skyrendermasked)
8507                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8508         }
8509         R_Mesh_ResetTextureState();
8510         GL_Color(1, 1, 1, 1);
8511 }
8512
8513 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
8514 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
8515 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8516 {
8517         qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
8518         qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
8519
8520         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
8521                 return;
8522
8523         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
8524                 R_Mesh_ColorPointer(NULL, 0, 0);
8525         else
8526                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
8527
8528         if (refract)
8529         {
8530                 // render background
8531                 GL_BlendFunc(GL_ONE, GL_ZERO);
8532                 GL_DepthMask(true);
8533                 GL_AlphaTest(false);
8534
8535                 GL_Color(1, 1, 1, 1);
8536                 R_Mesh_ColorPointer(NULL, 0, 0);
8537
8538                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
8539                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
8540                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8541                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
8542                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
8543                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
8544                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8545                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8546                 GL_LockArrays(0, 0);
8547
8548                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
8549                 GL_DepthMask(false);
8550                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
8551                         R_Mesh_ColorPointer(NULL, 0, 0);
8552                 else
8553                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
8554         }
8555
8556         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
8557
8558         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
8559         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8560         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
8561         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
8562         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
8563         if (!prepass)
8564                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8565
8566         if (refract)
8567         {
8568                 GL_BlendFunc(GL_ONE, GL_ZERO);
8569                 GL_DepthMask(true);
8570                 GL_AlphaTest(false);
8571         }
8572         else
8573         {
8574                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
8575                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8576                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
8577         }
8578
8579         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8580         {
8581                 if (refract || reflect)
8582                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8583                 else
8584                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
8585         }
8586         else
8587         {
8588                 if (refract || reflect)
8589                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8590                 else
8591                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8592         }
8593         GL_LockArrays(0, 0);
8594 }
8595
8596 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8597 {
8598         // OpenGL 1.3 path - anything not completely ancient
8599         int texturesurfaceindex;
8600         qboolean applycolor;
8601         qboolean applyfog;
8602         int layerindex;
8603         const texturelayer_t *layer;
8604         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8605
8606         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
8607         {
8608                 vec4_t layercolor;
8609                 int layertexrgbscale;
8610                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8611                 {
8612                         if (layerindex == 0)
8613                                 GL_AlphaTest(true);
8614                         else
8615                         {
8616                                 GL_AlphaTest(false);
8617                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
8618                         }
8619                 }
8620                 GL_DepthMask(layer->depthmask && writedepth);
8621                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
8622                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
8623                 {
8624                         layertexrgbscale = 4;
8625                         VectorScale(layer->color, 0.25f, layercolor);
8626                 }
8627                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
8628                 {
8629                         layertexrgbscale = 2;
8630                         VectorScale(layer->color, 0.5f, layercolor);
8631                 }
8632                 else
8633                 {
8634                         layertexrgbscale = 1;
8635                         VectorScale(layer->color, 1.0f, layercolor);
8636                 }
8637                 layercolor[3] = layer->color[3];
8638                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
8639                 R_Mesh_ColorPointer(NULL, 0, 0);
8640                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
8641                 switch (layer->type)
8642                 {
8643                 case TEXTURELAYERTYPE_LITTEXTURE:
8644                         // single-pass lightmapped texture with 2x rgbscale
8645                         //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8646                         R_Mesh_TexMatrix(0, NULL);
8647                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8648                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8649                         R_Mesh_TexBind(1, R_GetTexture(layer->texture));
8650                         R_Mesh_TexMatrix(1, &layer->texmatrix);
8651                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8652                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8653                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8654                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8655                         else if (rsurface.uselightmaptexture)
8656                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8657                         else
8658                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8659                         break;
8660                 case TEXTURELAYERTYPE_TEXTURE:
8661                         // singletexture unlit texture with transparency support
8662                         R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8663                         R_Mesh_TexMatrix(0, &layer->texmatrix);
8664                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8665                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8666                         R_Mesh_TexBind(1, 0);
8667                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
8668                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8669                         break;
8670                 case TEXTURELAYERTYPE_FOG:
8671                         // singletexture fogging
8672                         if (layer->texture)
8673                         {
8674                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8675                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8676                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8677                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8678                         }
8679                         else
8680                         {
8681                                 R_Mesh_TexBind(0, 0);
8682                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8683                         }
8684                         R_Mesh_TexBind(1, 0);
8685                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
8686                         // generate a color array for the fog pass
8687                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8688                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8689                         {
8690                                 int i;
8691                                 float f;
8692                                 const float *v;
8693                                 float *c;
8694                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8695                                 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)
8696                                 {
8697                                         f = 1 - RSurf_FogVertex(v);
8698                                         c[0] = layercolor[0];
8699                                         c[1] = layercolor[1];
8700                                         c[2] = layercolor[2];
8701                                         c[3] = f * layercolor[3];
8702                                 }
8703                         }
8704                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8705                         break;
8706                 default:
8707                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8708                 }
8709                 GL_LockArrays(0, 0);
8710         }
8711         CHECKGLERROR
8712         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8713         {
8714                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8715                 GL_AlphaTest(false);
8716         }
8717 }
8718
8719 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8720 {
8721         // OpenGL 1.1 - crusty old voodoo path
8722         int texturesurfaceindex;
8723         qboolean applyfog;
8724         int layerindex;
8725         const texturelayer_t *layer;
8726         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8727
8728         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
8729         {
8730                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8731                 {
8732                         if (layerindex == 0)
8733                                 GL_AlphaTest(true);
8734                         else
8735                         {
8736                                 GL_AlphaTest(false);
8737                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
8738                         }
8739                 }
8740                 GL_DepthMask(layer->depthmask && writedepth);
8741                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
8742                 R_Mesh_ColorPointer(NULL, 0, 0);
8743                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
8744                 switch (layer->type)
8745                 {
8746                 case TEXTURELAYERTYPE_LITTEXTURE:
8747                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
8748                         {
8749                                 // two-pass lit texture with 2x rgbscale
8750                                 // first the lightmap pass
8751                                 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8752                                 R_Mesh_TexMatrix(0, NULL);
8753                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8754                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8755                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8756                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8757                                 else if (rsurface.uselightmaptexture)
8758                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8759                                 else
8760                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8761                                 GL_LockArrays(0, 0);
8762                                 // then apply the texture to it
8763                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8764                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8765                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8766                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8767                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8768                                 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);
8769                         }
8770                         else
8771                         {
8772                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
8773                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8774                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8775                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8776                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8777                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8778                                         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);
8779                                 else
8780                                         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);
8781                         }
8782                         break;
8783                 case TEXTURELAYERTYPE_TEXTURE:
8784                         // singletexture unlit texture with transparency support
8785                         R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8786                         R_Mesh_TexMatrix(0, &layer->texmatrix);
8787                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8788                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8789                         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);
8790                         break;
8791                 case TEXTURELAYERTYPE_FOG:
8792                         // singletexture fogging
8793                         if (layer->texture)
8794                         {
8795                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8796                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8797                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8798                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8799                         }
8800                         else
8801                         {
8802                                 R_Mesh_TexBind(0, 0);
8803                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8804                         }
8805                         // generate a color array for the fog pass
8806                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8807                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8808                         {
8809                                 int i;
8810                                 float f;
8811                                 const float *v;
8812                                 float *c;
8813                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8814                                 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)
8815                                 {
8816                                         f = 1 - RSurf_FogVertex(v);
8817                                         c[0] = layer->color[0];
8818                                         c[1] = layer->color[1];
8819                                         c[2] = layer->color[2];
8820                                         c[3] = f * layer->color[3];
8821                                 }
8822                         }
8823                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8824                         break;
8825                 default:
8826                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8827                 }
8828                 GL_LockArrays(0, 0);
8829         }
8830         CHECKGLERROR
8831         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8832         {
8833                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8834                 GL_AlphaTest(false);
8835         }
8836 }
8837
8838 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8839 {
8840         float c[4];
8841
8842         GL_AlphaTest(false);
8843         R_Mesh_ColorPointer(NULL, 0, 0);
8844         R_Mesh_ResetTextureState();
8845         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8846
8847         if(rsurface.texture && rsurface.texture->currentskinframe)
8848         {
8849                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8850                 c[3] *= rsurface.texture->currentalpha;
8851         }
8852         else
8853         {
8854                 c[0] = 1;
8855                 c[1] = 0;
8856                 c[2] = 1;
8857                 c[3] = 1;
8858         }
8859
8860         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
8861         {
8862                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8863                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8864                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8865         }
8866
8867         // brighten it up (as texture value 127 means "unlit")
8868         c[0] *= 2 * r_refdef.view.colorscale;
8869         c[1] *= 2 * r_refdef.view.colorscale;
8870         c[2] *= 2 * r_refdef.view.colorscale;
8871
8872         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8873                 c[3] *= r_wateralpha.value;
8874
8875         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8876         {
8877                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8878                 GL_DepthMask(false);
8879         }
8880         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8881         {
8882                 GL_BlendFunc(GL_ONE, GL_ONE);
8883                 GL_DepthMask(false);
8884         }
8885         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8886         {
8887                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8888                 GL_DepthMask(false);
8889         }
8890         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8891         {
8892                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8893                 GL_DepthMask(false);
8894         }
8895         else
8896         {
8897                 GL_BlendFunc(GL_ONE, GL_ZERO);
8898                 GL_DepthMask(writedepth);
8899         }
8900
8901         rsurface.lightmapcolor4f = NULL;
8902
8903         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8904         {
8905                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8906
8907                 rsurface.lightmapcolor4f = NULL;
8908                 rsurface.lightmapcolor4f_bufferobject = 0;
8909                 rsurface.lightmapcolor4f_bufferoffset = 0;
8910         }
8911         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8912         {
8913                 qboolean applycolor = true;
8914                 float one = 1.0;
8915
8916                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8917
8918                 r_refdef.lightmapintensity = 1;
8919                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8920                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8921         }
8922         else
8923         {
8924                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8925
8926                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8927                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8928                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8929         }
8930
8931         if(!rsurface.lightmapcolor4f)
8932                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8933
8934         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8935         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8936         if(r_refdef.fogenabled)
8937                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8938
8939         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8940         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8941 }
8942
8943 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8944 {
8945         CHECKGLERROR
8946         RSurf_SetupDepthAndCulling();
8947         if (r_showsurfaces.integer == 3 && !prepass)
8948         {
8949                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8950                 return;
8951         }
8952         switch (vid.renderpath)
8953         {
8954         case RENDERPATH_GL20:
8955         case RENDERPATH_CGGL:
8956                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8957                 break;
8958         case RENDERPATH_GL13:
8959                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8960                 break;
8961         case RENDERPATH_GL11:
8962                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8963                 break;
8964         }
8965         CHECKGLERROR
8966 }
8967
8968 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8969 {
8970         CHECKGLERROR
8971         RSurf_SetupDepthAndCulling();
8972         if (r_showsurfaces.integer == 3 && !prepass)
8973         {
8974                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8975                 return;
8976         }
8977         switch (vid.renderpath)
8978         {
8979         case RENDERPATH_GL20:
8980         case RENDERPATH_CGGL:
8981                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8982                 break;
8983         case RENDERPATH_GL13:
8984                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8985                 break;
8986         case RENDERPATH_GL11:
8987                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8988                 break;
8989         }
8990         CHECKGLERROR
8991 }
8992
8993 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8994 {
8995         int i, j;
8996         int texturenumsurfaces, endsurface;
8997         texture_t *texture;
8998         const msurface_t *surface;
8999         const msurface_t *texturesurfacelist[256];
9000
9001         // if the model is static it doesn't matter what value we give for
9002         // wantnormals and wanttangents, so this logic uses only rules applicable
9003         // to a model, knowing that they are meaningless otherwise
9004         if (ent == r_refdef.scene.worldentity)
9005                 RSurf_ActiveWorldEntity();
9006         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9007                 RSurf_ActiveModelEntity(ent, false, false, false);
9008         else
9009         {
9010                 switch (vid.renderpath)
9011                 {
9012                 case RENDERPATH_GL20:
9013                 case RENDERPATH_CGGL:
9014                         RSurf_ActiveModelEntity(ent, true, true, false);
9015                         break;
9016                 case RENDERPATH_GL13:
9017                 case RENDERPATH_GL11:
9018                         RSurf_ActiveModelEntity(ent, true, false, false);
9019                         break;
9020                 }
9021         }
9022
9023         if (r_transparentdepthmasking.integer)
9024         {
9025                 qboolean setup = false;
9026                 for (i = 0;i < numsurfaces;i = j)
9027                 {
9028                         j = i + 1;
9029                         surface = rsurface.modelsurfaces + surfacelist[i];
9030                         texture = surface->texture;
9031                         rsurface.texture = R_GetCurrentTexture(texture);
9032                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9033                         // scan ahead until we find a different texture
9034                         endsurface = min(i + 1024, numsurfaces);
9035                         texturenumsurfaces = 0;
9036                         texturesurfacelist[texturenumsurfaces++] = surface;
9037                         for (;j < endsurface;j++)
9038                         {
9039                                 surface = rsurface.modelsurfaces + surfacelist[j];
9040                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
9041                                         break;
9042                                 texturesurfacelist[texturenumsurfaces++] = surface;
9043                         }
9044                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9045                                 continue;
9046                         // render the range of surfaces as depth
9047                         if (!setup)
9048                         {
9049                                 setup = true;
9050                                 GL_ColorMask(0,0,0,0);
9051                                 GL_Color(1,1,1,1);
9052                                 GL_DepthTest(true);
9053                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9054                                 GL_DepthMask(true);
9055                                 GL_AlphaTest(false);
9056                                 R_Mesh_ColorPointer(NULL, 0, 0);
9057                                 R_Mesh_ResetTextureState();
9058                                 R_SetupShader_DepthOrShadow();
9059                         }
9060                         RSurf_SetupDepthAndCulling();
9061                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9062                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9063                 }
9064                 if (setup)
9065                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9066         }
9067
9068         for (i = 0;i < numsurfaces;i = j)
9069         {
9070                 j = i + 1;
9071                 surface = rsurface.modelsurfaces + surfacelist[i];
9072                 texture = surface->texture;
9073                 rsurface.texture = R_GetCurrentTexture(texture);
9074                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9075                 // scan ahead until we find a different texture
9076                 endsurface = min(i + 1024, numsurfaces);
9077                 texturenumsurfaces = 0;
9078                 texturesurfacelist[texturenumsurfaces++] = surface;
9079                 for (;j < endsurface;j++)
9080                 {
9081                         surface = rsurface.modelsurfaces + surfacelist[j];
9082                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
9083                                 break;
9084                         texturesurfacelist[texturenumsurfaces++] = surface;
9085                 }
9086                 // render the range of surfaces
9087                 if (ent == r_refdef.scene.worldentity)
9088                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9089                 else
9090                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9091         }
9092         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9093         GL_AlphaTest(false);
9094 }
9095
9096 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9097 {
9098         // transparent surfaces get pushed off into the transparent queue
9099         int surfacelistindex;
9100         const msurface_t *surface;
9101         vec3_t tempcenter, center;
9102         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9103         {
9104                 surface = texturesurfacelist[surfacelistindex];
9105                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9106                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9107                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9108                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9109                 if (queueentity->transparent_offset) // transparent offset
9110                 {
9111                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9112                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9113                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9114                 }
9115                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9116         }
9117 }
9118
9119 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9120 {
9121         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9122         CHECKGLERROR
9123         if (depthonly)
9124         {
9125                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9126                         return;
9127                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9128                         return;
9129                 RSurf_SetupDepthAndCulling();
9130                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9131                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9132         }
9133         else if (prepass)
9134         {
9135                 if (!rsurface.texture->currentnumlayers)
9136                         return;
9137                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9138                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9139                 else
9140                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9141         }
9142         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
9143         {
9144                 RSurf_SetupDepthAndCulling();
9145                 GL_AlphaTest(false);
9146                 R_Mesh_ColorPointer(NULL, 0, 0);
9147                 R_Mesh_ResetTextureState();
9148                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9149                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9150                 GL_DepthMask(true);
9151                 GL_BlendFunc(GL_ONE, GL_ZERO);
9152                 GL_Color(0, 0, 0, 1);
9153                 GL_DepthTest(writedepth);
9154                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9155         }
9156         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
9157         {
9158                 RSurf_SetupDepthAndCulling();
9159                 GL_AlphaTest(false);
9160                 R_Mesh_ColorPointer(NULL, 0, 0);
9161                 R_Mesh_ResetTextureState();
9162                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9163                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9164                 GL_DepthMask(true);
9165                 GL_BlendFunc(GL_ONE, GL_ZERO);
9166                 GL_DepthTest(true);
9167                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
9168         }
9169         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
9170                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9171         else if (!rsurface.texture->currentnumlayers)
9172                 return;
9173         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9174         {
9175                 // in the deferred case, transparent surfaces were queued during prepass
9176                 if (!r_shadow_usingdeferredprepass)
9177                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9178         }
9179         else
9180         {
9181                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9182                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9183         }
9184         CHECKGLERROR
9185 }
9186
9187 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9188 {
9189         int i, j;
9190         texture_t *texture;
9191         // break the surface list down into batches by texture and use of lightmapping
9192         for (i = 0;i < numsurfaces;i = j)
9193         {
9194                 j = i + 1;
9195                 // texture is the base texture pointer, rsurface.texture is the
9196                 // current frame/skin the texture is directing us to use (for example
9197                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9198                 // use skin 1 instead)
9199                 texture = surfacelist[i]->texture;
9200                 rsurface.texture = R_GetCurrentTexture(texture);
9201                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
9202                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9203                 {
9204                         // if this texture is not the kind we want, skip ahead to the next one
9205                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9206                                 ;
9207                         continue;
9208                 }
9209                 // simply scan ahead until we find a different texture or lightmap state
9210                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
9211                         ;
9212                 // render the range of surfaces
9213                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
9214         }
9215 }
9216
9217 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
9218 {
9219         CHECKGLERROR
9220         if (depthonly)
9221         {
9222                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9223                         return;
9224                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9225                         return;
9226                 RSurf_SetupDepthAndCulling();
9227                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9228                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9229         }
9230         else if (prepass)
9231         {
9232                 if (!rsurface.texture->currentnumlayers)
9233                         return;
9234                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9235                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9236                 else
9237                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9238         }
9239         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
9240         {
9241                 RSurf_SetupDepthAndCulling();
9242                 GL_AlphaTest(false);
9243                 R_Mesh_ColorPointer(NULL, 0, 0);
9244                 R_Mesh_ResetTextureState();
9245                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9246                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9247                 GL_DepthMask(true);
9248                 GL_BlendFunc(GL_ONE, GL_ZERO);
9249                 GL_Color(0, 0, 0, 1);
9250                 GL_DepthTest(writedepth);
9251                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9252         }
9253         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9254         {
9255                 RSurf_SetupDepthAndCulling();
9256                 GL_AlphaTest(false);
9257                 R_Mesh_ColorPointer(NULL, 0, 0);
9258                 R_Mesh_ResetTextureState();
9259                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9260                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9261                 GL_DepthMask(true);
9262                 GL_BlendFunc(GL_ONE, GL_ZERO);
9263                 GL_DepthTest(true);
9264                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
9265         }
9266         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
9267                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9268         else if (!rsurface.texture->currentnumlayers)
9269                 return;
9270         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9271         {
9272                 // in the deferred case, transparent surfaces were queued during prepass
9273                 if (!r_shadow_usingdeferredprepass)
9274                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9275         }
9276         else
9277         {
9278                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9279                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9280         }
9281         CHECKGLERROR
9282 }
9283
9284 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9285 {
9286         int i, j;
9287         texture_t *texture;
9288         // break the surface list down into batches by texture and use of lightmapping
9289         for (i = 0;i < numsurfaces;i = j)
9290         {
9291                 j = i + 1;
9292                 // texture is the base texture pointer, rsurface.texture is the
9293                 // current frame/skin the texture is directing us to use (for example
9294                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9295                 // use skin 1 instead)
9296                 texture = surfacelist[i]->texture;
9297                 rsurface.texture = R_GetCurrentTexture(texture);
9298                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
9299                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9300                 {
9301                         // if this texture is not the kind we want, skip ahead to the next one
9302                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9303                                 ;
9304                         continue;
9305                 }
9306                 // simply scan ahead until we find a different texture or lightmap state
9307                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
9308                         ;
9309                 // render the range of surfaces
9310                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
9311         }
9312 }
9313
9314 float locboxvertex3f[6*4*3] =
9315 {
9316         1,0,1, 1,0,0, 1,1,0, 1,1,1,
9317         0,1,1, 0,1,0, 0,0,0, 0,0,1,
9318         1,1,1, 1,1,0, 0,1,0, 0,1,1,
9319         0,0,1, 0,0,0, 1,0,0, 1,0,1,
9320         0,0,1, 1,0,1, 1,1,1, 0,1,1,
9321         1,0,0, 0,0,0, 0,1,0, 1,1,0
9322 };
9323
9324 unsigned short locboxelements[6*2*3] =
9325 {
9326          0, 1, 2, 0, 2, 3,
9327          4, 5, 6, 4, 6, 7,
9328          8, 9,10, 8,10,11,
9329         12,13,14, 12,14,15,
9330         16,17,18, 16,18,19,
9331         20,21,22, 20,22,23
9332 };
9333
9334 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9335 {
9336         int i, j;
9337         cl_locnode_t *loc = (cl_locnode_t *)ent;
9338         vec3_t mins, size;
9339         float vertex3f[6*4*3];
9340         CHECKGLERROR
9341         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9342         GL_DepthMask(false);
9343         GL_DepthRange(0, 1);
9344         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9345         GL_DepthTest(true);
9346         GL_CullFace(GL_NONE);
9347         R_EntityMatrix(&identitymatrix);
9348
9349         R_Mesh_VertexPointer(vertex3f, 0, 0);
9350         R_Mesh_ColorPointer(NULL, 0, 0);
9351         R_Mesh_ResetTextureState();
9352         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9353
9354         i = surfacelist[0];
9355         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9356                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9357                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9358                         surfacelist[0] < 0 ? 0.5f : 0.125f);
9359
9360         if (VectorCompare(loc->mins, loc->maxs))
9361         {
9362                 VectorSet(size, 2, 2, 2);
9363                 VectorMA(loc->mins, -0.5f, size, mins);
9364         }
9365         else
9366         {
9367                 VectorCopy(loc->mins, mins);
9368                 VectorSubtract(loc->maxs, loc->mins, size);
9369         }
9370
9371         for (i = 0;i < 6*4*3;)
9372                 for (j = 0;j < 3;j++, i++)
9373                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
9374
9375         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
9376 }
9377
9378 void R_DrawLocs(void)
9379 {
9380         int index;
9381         cl_locnode_t *loc, *nearestloc;
9382         vec3_t center;
9383         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
9384         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
9385         {
9386                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
9387                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
9388         }
9389 }
9390
9391 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
9392 {
9393         if (decalsystem->decals)
9394                 Mem_Free(decalsystem->decals);
9395         memset(decalsystem, 0, sizeof(*decalsystem));
9396 }
9397
9398 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)
9399 {
9400         tridecal_t *decal;
9401         tridecal_t *decals;
9402         int i;
9403         int maxdecals;
9404
9405         // expand or initialize the system
9406         if (decalsystem->maxdecals <= decalsystem->numdecals)
9407         {
9408                 decalsystem_t old = *decalsystem;
9409                 qboolean useshortelements;
9410                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
9411                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
9412                 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)));
9413                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
9414                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
9415                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
9416                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
9417                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
9418                 if (decalsystem->numdecals)
9419                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
9420                 if (old.decals)
9421                         Mem_Free(old.decals);
9422                 for (i = 0;i < decalsystem->maxdecals*3;i++)
9423                         decalsystem->element3i[i] = i;
9424                 if (useshortelements)
9425                         for (i = 0;i < decalsystem->maxdecals*3;i++)
9426                                 decalsystem->element3s[i] = i;
9427         }
9428
9429         // grab a decal and search for another free slot for the next one
9430         maxdecals = decalsystem->maxdecals;
9431         decals = decalsystem->decals;
9432         decal = decalsystem->decals + (i = decalsystem->freedecal++);
9433         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
9434                 ;
9435         decalsystem->freedecal = i;
9436         if (decalsystem->numdecals <= i)
9437                 decalsystem->numdecals = i + 1;
9438
9439         // initialize the decal
9440         decal->lived = 0;
9441         decal->triangleindex = triangleindex;
9442         decal->surfaceindex = surfaceindex;
9443         decal->decalsequence = decalsequence;
9444         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
9445         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
9446         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
9447         decal->color4ub[0][3] = 255;
9448         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
9449         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
9450         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
9451         decal->color4ub[1][3] = 255;
9452         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
9453         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
9454         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
9455         decal->color4ub[2][3] = 255;
9456         decal->vertex3f[0][0] = v0[0];
9457         decal->vertex3f[0][1] = v0[1];
9458         decal->vertex3f[0][2] = v0[2];
9459         decal->vertex3f[1][0] = v1[0];
9460         decal->vertex3f[1][1] = v1[1];
9461         decal->vertex3f[1][2] = v1[2];
9462         decal->vertex3f[2][0] = v2[0];
9463         decal->vertex3f[2][1] = v2[1];
9464         decal->vertex3f[2][2] = v2[2];
9465         decal->texcoord2f[0][0] = t0[0];
9466         decal->texcoord2f[0][1] = t0[1];
9467         decal->texcoord2f[1][0] = t1[0];
9468         decal->texcoord2f[1][1] = t1[1];
9469         decal->texcoord2f[2][0] = t2[0];
9470         decal->texcoord2f[2][1] = t2[1];
9471 }
9472
9473 extern cvar_t cl_decals_bias;
9474 extern cvar_t cl_decals_models;
9475 extern cvar_t cl_decals_newsystem_intensitymultiplier;
9476 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)
9477 {
9478         matrix4x4_t projection;
9479         decalsystem_t *decalsystem;
9480         qboolean dynamic;
9481         dp_model_t *model;
9482         const float *vertex3f;
9483         const msurface_t *surface;
9484         const msurface_t *surfaces;
9485         const int *surfacelist;
9486         const texture_t *texture;
9487         int numvertices;
9488         int numtriangles;
9489         int numsurfacelist;
9490         int surfacelistindex;
9491         int surfaceindex;
9492         int triangleindex;
9493         int decalsurfaceindex;
9494         int cornerindex;
9495         int index;
9496         int numpoints;
9497         const int *e;
9498         float localorigin[3];
9499         float localnormal[3];
9500         float localmins[3];
9501         float localmaxs[3];
9502         float localsize;
9503         float ilocalsize;
9504         float v[9][3];
9505         float tc[9][2];
9506         float c[9][4];
9507         //float normal[3];
9508         float planes[6][4];
9509         float f;
9510         float points[2][9][3];
9511         float angles[3];
9512         float temp[3];
9513
9514         decalsystem = &ent->decalsystem;
9515         model = ent->model;
9516         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
9517         {
9518                 R_DecalSystem_Reset(&ent->decalsystem);
9519                 return;
9520         }
9521
9522         if (!model->brush.data_nodes && !cl_decals_models.integer)
9523         {
9524                 if (decalsystem->model)
9525                         R_DecalSystem_Reset(decalsystem);
9526                 return;
9527         }
9528
9529         if (decalsystem->model != model)
9530                 R_DecalSystem_Reset(decalsystem);
9531         decalsystem->model = model;
9532
9533         RSurf_ActiveModelEntity(ent, false, false, false);
9534
9535         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
9536         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
9537         VectorNormalize(localnormal);
9538         localsize = worldsize*rsurface.inversematrixscale;
9539         ilocalsize = 1.0f / localsize;
9540         localmins[0] = localorigin[0] - localsize;
9541         localmins[1] = localorigin[1] - localsize;
9542         localmins[2] = localorigin[2] - localsize;
9543         localmaxs[0] = localorigin[0] + localsize;
9544         localmaxs[1] = localorigin[1] + localsize;
9545         localmaxs[2] = localorigin[2] + localsize;
9546
9547         //VectorCopy(localnormal, planes[4]);
9548         //VectorVectors(planes[4], planes[2], planes[0]);
9549         AnglesFromVectors(angles, localnormal, NULL, false);
9550         AngleVectors(angles, planes[0], planes[2], planes[4]);
9551         VectorNegate(planes[0], planes[1]);
9552         VectorNegate(planes[2], planes[3]);
9553         VectorNegate(planes[4], planes[5]);
9554         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
9555         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
9556         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
9557         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
9558         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
9559         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
9560
9561 #if 1
9562 // works
9563 {
9564         matrix4x4_t forwardprojection;
9565         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
9566         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
9567 }
9568 #else
9569 // broken
9570 {
9571         float projectionvector[4][3];
9572         VectorScale(planes[0], ilocalsize, projectionvector[0]);
9573         VectorScale(planes[2], ilocalsize, projectionvector[1]);
9574         VectorScale(planes[4], ilocalsize, projectionvector[2]);
9575         projectionvector[0][0] = planes[0][0] * ilocalsize;
9576         projectionvector[0][1] = planes[1][0] * ilocalsize;
9577         projectionvector[0][2] = planes[2][0] * ilocalsize;
9578         projectionvector[1][0] = planes[0][1] * ilocalsize;
9579         projectionvector[1][1] = planes[1][1] * ilocalsize;
9580         projectionvector[1][2] = planes[2][1] * ilocalsize;
9581         projectionvector[2][0] = planes[0][2] * ilocalsize;
9582         projectionvector[2][1] = planes[1][2] * ilocalsize;
9583         projectionvector[2][2] = planes[2][2] * ilocalsize;
9584         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
9585         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
9586         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
9587         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
9588 }
9589 #endif
9590
9591         dynamic = model->surfmesh.isanimated;
9592         vertex3f = rsurface.modelvertex3f;
9593         numsurfacelist = model->nummodelsurfaces;
9594         surfacelist = model->sortedmodelsurfaces;
9595         surfaces = model->data_surfaces;
9596         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
9597         {
9598                 surfaceindex = surfacelist[surfacelistindex];
9599                 surface = surfaces + surfaceindex;
9600                 // skip transparent surfaces
9601                 texture = surface->texture;
9602                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9603                         continue;
9604                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
9605                         continue;
9606                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
9607                         continue;
9608                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
9609                 numvertices = surface->num_vertices;
9610                 numtriangles = surface->num_triangles;
9611                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
9612                 {
9613                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
9614                         {
9615                                 index = 3*e[cornerindex];
9616                                 VectorCopy(vertex3f + index, v[cornerindex]);
9617                         }
9618                         // cull backfaces
9619                         //TriangleNormal(v[0], v[1], v[2], normal);
9620                         //if (DotProduct(normal, localnormal) < 0.0f)
9621                         //      continue;
9622                         // clip by each of the box planes formed from the projection matrix
9623                         // if anything survives, we emit the decal
9624                         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]);
9625                         if (numpoints < 3)
9626                                 continue;
9627                         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]);
9628                         if (numpoints < 3)
9629                                 continue;
9630                         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]);
9631                         if (numpoints < 3)
9632                                 continue;
9633                         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]);
9634                         if (numpoints < 3)
9635                                 continue;
9636                         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]);
9637                         if (numpoints < 3)
9638                                 continue;
9639                         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]);
9640                         if (numpoints < 3)
9641                                 continue;
9642                         // some part of the triangle survived, so we have to accept it...
9643                         if (dynamic)
9644                         {
9645                                 // dynamic always uses the original triangle
9646                                 numpoints = 3;
9647                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9648                                 {
9649                                         index = 3*e[cornerindex];
9650                                         VectorCopy(vertex3f + index, v[cornerindex]);
9651                                 }
9652                         }
9653                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
9654                         {
9655                                 // convert vertex positions to texcoords
9656                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
9657                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
9658                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
9659                                 // calculate distance fade from the projection origin
9660                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
9661                                 f = bound(0.0f, f, 1.0f);
9662                                 c[cornerindex][0] = r * f;
9663                                 c[cornerindex][1] = g * f;
9664                                 c[cornerindex][2] = b * f;
9665                                 c[cornerindex][3] = 1.0f;
9666                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
9667                         }
9668                         if (dynamic)
9669                                 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);
9670                         else
9671                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
9672                                         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);
9673                 }
9674         }
9675 }
9676
9677 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
9678 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)
9679 {
9680         int renderentityindex;
9681         float worldmins[3];
9682         float worldmaxs[3];
9683         entity_render_t *ent;
9684
9685         if (!cl_decals_newsystem.integer)
9686                 return;
9687
9688         worldmins[0] = worldorigin[0] - worldsize;
9689         worldmins[1] = worldorigin[1] - worldsize;
9690         worldmins[2] = worldorigin[2] - worldsize;
9691         worldmaxs[0] = worldorigin[0] + worldsize;
9692         worldmaxs[1] = worldorigin[1] + worldsize;
9693         worldmaxs[2] = worldorigin[2] + worldsize;
9694
9695         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9696
9697         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
9698         {
9699                 ent = r_refdef.scene.entities[renderentityindex];
9700                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
9701                         continue;
9702
9703                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9704         }
9705 }
9706
9707 typedef struct r_decalsystem_splatqueue_s
9708 {
9709         vec3_t worldorigin;
9710         vec3_t worldnormal;
9711         float color[4];
9712         float tcrange[4];
9713         float worldsize;
9714         int decalsequence;
9715 }
9716 r_decalsystem_splatqueue_t;
9717
9718 int r_decalsystem_numqueued = 0;
9719 #define MAX_DECALSYSTEM_QUEUE 1024
9720 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
9721
9722 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)
9723 {
9724         r_decalsystem_splatqueue_t *queue;
9725
9726         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
9727                 return;
9728
9729         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
9730         VectorCopy(worldorigin, queue->worldorigin);
9731         VectorCopy(worldnormal, queue->worldnormal);
9732         Vector4Set(queue->color, r, g, b, a);
9733         Vector4Set(queue->tcrange, s1, t1, s2, t2);
9734         queue->worldsize = worldsize;
9735         queue->decalsequence = cl.decalsequence++;
9736 }
9737
9738 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
9739 {
9740         int i;
9741         r_decalsystem_splatqueue_t *queue;
9742
9743         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
9744                 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);
9745         r_decalsystem_numqueued = 0;
9746 }
9747
9748 extern cvar_t cl_decals_max;
9749 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
9750 {
9751         int i;
9752         decalsystem_t *decalsystem = &ent->decalsystem;
9753         int numdecals;
9754         int killsequence;
9755         tridecal_t *decal;
9756         float frametime;
9757         float lifetime;
9758
9759         if (!decalsystem->numdecals)
9760                 return;
9761
9762         if (r_showsurfaces.integer)
9763                 return;
9764
9765         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9766         {
9767                 R_DecalSystem_Reset(decalsystem);
9768                 return;
9769         }
9770
9771         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
9772         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
9773
9774         if (decalsystem->lastupdatetime)
9775                 frametime = (cl.time - decalsystem->lastupdatetime);
9776         else
9777                 frametime = 0;
9778         decalsystem->lastupdatetime = cl.time;
9779         decal = decalsystem->decals;
9780         numdecals = decalsystem->numdecals;
9781
9782         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9783         {
9784                 if (decal->color4ub[0][3])
9785                 {
9786                         decal->lived += frametime;
9787                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
9788                         {
9789                                 memset(decal, 0, sizeof(*decal));
9790                                 if (decalsystem->freedecal > i)
9791                                         decalsystem->freedecal = i;
9792                         }
9793                 }
9794         }
9795         decal = decalsystem->decals;
9796         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
9797                 numdecals--;
9798
9799         // collapse the array by shuffling the tail decals into the gaps
9800         for (;;)
9801         {
9802                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
9803                         decalsystem->freedecal++;
9804                 if (decalsystem->freedecal == numdecals)
9805                         break;
9806                 decal[decalsystem->freedecal] = decal[--numdecals];
9807         }
9808
9809         decalsystem->numdecals = numdecals;
9810
9811         if (numdecals <= 0)
9812         {
9813                 // if there are no decals left, reset decalsystem
9814                 R_DecalSystem_Reset(decalsystem);
9815         }
9816 }
9817
9818 extern skinframe_t *decalskinframe;
9819 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9820 {
9821         int i;
9822         decalsystem_t *decalsystem = &ent->decalsystem;
9823         int numdecals;
9824         tridecal_t *decal;
9825         float fadedelay;
9826         float faderate;
9827         float alpha;
9828         float *v3f;
9829         float *c4f;
9830         float *t2f;
9831         const int *e;
9832         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9833         int numtris = 0;
9834
9835         numdecals = decalsystem->numdecals;
9836         if (!numdecals)
9837                 return;
9838
9839         if (r_showsurfaces.integer)
9840                 return;
9841
9842         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9843         {
9844                 R_DecalSystem_Reset(decalsystem);
9845                 return;
9846         }
9847
9848         // if the model is static it doesn't matter what value we give for
9849         // wantnormals and wanttangents, so this logic uses only rules applicable
9850         // to a model, knowing that they are meaningless otherwise
9851         if (ent == r_refdef.scene.worldentity)
9852                 RSurf_ActiveWorldEntity();
9853         else
9854                 RSurf_ActiveModelEntity(ent, false, false, false);
9855
9856         decalsystem->lastupdatetime = cl.time;
9857         decal = decalsystem->decals;
9858
9859         fadedelay = cl_decals_time.value;
9860         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9861
9862         // update vertex positions for animated models
9863         v3f = decalsystem->vertex3f;
9864         c4f = decalsystem->color4f;
9865         t2f = decalsystem->texcoord2f;
9866         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9867         {
9868                 if (!decal->color4ub[0][3])
9869                         continue;
9870
9871                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9872                         continue;
9873
9874                 // update color values for fading decals
9875                 if (decal->lived >= cl_decals_time.value)
9876                 {
9877                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9878                         alpha *= (1.0f/255.0f);
9879                 }
9880                 else
9881                         alpha = 1.0f/255.0f;
9882
9883                 c4f[ 0] = decal->color4ub[0][0] * alpha;
9884                 c4f[ 1] = decal->color4ub[0][1] * alpha;
9885                 c4f[ 2] = decal->color4ub[0][2] * alpha;
9886                 c4f[ 3] = 1;
9887                 c4f[ 4] = decal->color4ub[1][0] * alpha;
9888                 c4f[ 5] = decal->color4ub[1][1] * alpha;
9889                 c4f[ 6] = decal->color4ub[1][2] * alpha;
9890                 c4f[ 7] = 1;
9891                 c4f[ 8] = decal->color4ub[2][0] * alpha;
9892                 c4f[ 9] = decal->color4ub[2][1] * alpha;
9893                 c4f[10] = decal->color4ub[2][2] * alpha;
9894                 c4f[11] = 1;
9895
9896                 t2f[0] = decal->texcoord2f[0][0];
9897                 t2f[1] = decal->texcoord2f[0][1];
9898                 t2f[2] = decal->texcoord2f[1][0];
9899                 t2f[3] = decal->texcoord2f[1][1];
9900                 t2f[4] = decal->texcoord2f[2][0];
9901                 t2f[5] = decal->texcoord2f[2][1];
9902
9903                 // update vertex positions for animated models
9904                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9905                 {
9906                         e = rsurface.modelelement3i + 3*decal->triangleindex;
9907                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9908                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9909                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9910                 }
9911                 else
9912                 {
9913                         VectorCopy(decal->vertex3f[0], v3f);
9914                         VectorCopy(decal->vertex3f[1], v3f + 3);
9915                         VectorCopy(decal->vertex3f[2], v3f + 6);
9916                 }
9917
9918                 v3f += 9;
9919                 c4f += 12;
9920                 t2f += 6;
9921                 numtris++;
9922         }
9923
9924         if (numtris > 0)
9925         {
9926                 r_refdef.stats.drawndecals += numtris;
9927
9928                 if (r_refdef.fogenabled)
9929                 {
9930                         switch(vid.renderpath)
9931                         {
9932                         case RENDERPATH_GL20:
9933                         case RENDERPATH_CGGL:
9934                         case RENDERPATH_GL13:
9935                         case RENDERPATH_GL11:
9936                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
9937                                 {
9938                                         alpha = RSurf_FogVertex(v3f);
9939                                         c4f[0] *= alpha;
9940                                         c4f[1] *= alpha;
9941                                         c4f[2] *= alpha;
9942                                 }
9943                                 break;
9944                         }
9945                 }
9946
9947                 // now render the decals all at once
9948                 // (this assumes they all use one particle font texture!)
9949                 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);
9950                 R_Mesh_ResetTextureState();
9951                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9952                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9953                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9954                 GL_DepthMask(false);
9955                 GL_DepthRange(0, 1);
9956                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9957                 GL_DepthTest(true);
9958                 GL_CullFace(GL_NONE);
9959                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9960                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
9961                 GL_LockArrays(0, numtris * 3);
9962                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9963                 GL_LockArrays(0, 0);
9964         }
9965 }
9966
9967 static void R_DrawModelDecals(void)
9968 {
9969         int i, numdecals;
9970
9971         // fade faster when there are too many decals
9972         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9973         for (i = 0;i < r_refdef.scene.numentities;i++)
9974                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9975
9976         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9977         for (i = 0;i < r_refdef.scene.numentities;i++)
9978                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9979                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9980
9981         R_DecalSystem_ApplySplatEntitiesQueue();
9982
9983         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9984         for (i = 0;i < r_refdef.scene.numentities;i++)
9985                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9986
9987         r_refdef.stats.totaldecals += numdecals;
9988
9989         if (r_showsurfaces.integer)
9990                 return;
9991
9992         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9993
9994         for (i = 0;i < r_refdef.scene.numentities;i++)
9995         {
9996                 if (!r_refdef.viewcache.entityvisible[i])
9997                         continue;
9998                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9999                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10000         }
10001 }
10002
10003 void R_DrawDebugModel(void)
10004 {
10005         entity_render_t *ent = rsurface.entity;
10006         int i, j, k, l, flagsmask;
10007         const int *elements;
10008         q3mbrush_t *brush;
10009         const msurface_t *surface;
10010         dp_model_t *model = ent->model;
10011         vec3_t v;
10012
10013         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10014
10015         R_Mesh_ColorPointer(NULL, 0, 0);
10016         R_Mesh_ResetTextureState();
10017         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10018         GL_DepthRange(0, 1);
10019         GL_DepthTest(!r_showdisabledepthtest.integer);
10020         GL_DepthMask(false);
10021         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10022
10023         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
10024         {
10025                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10026                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
10027                 {
10028                         if (brush->colbrushf && brush->colbrushf->numtriangles)
10029                         {
10030                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
10031                                 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);
10032                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
10033                         }
10034                 }
10035                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
10036                 {
10037                         if (surface->num_collisiontriangles)
10038                         {
10039                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
10040                                 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);
10041                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
10042                         }
10043                 }
10044         }
10045
10046         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10047
10048         if (r_showtris.integer || r_shownormals.integer)
10049         {
10050                 if (r_showdisabledepthtest.integer)
10051                 {
10052                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10053                         GL_DepthMask(false);
10054                 }
10055                 else
10056                 {
10057                         GL_BlendFunc(GL_ONE, GL_ZERO);
10058                         GL_DepthMask(true);
10059                 }
10060                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10061                 {
10062                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10063                                 continue;
10064                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10065                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10066                         {
10067                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
10068                                 if (r_showtris.value > 0)
10069                                 {
10070                                         if (!rsurface.texture->currentlayers->depthmask)
10071                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10072                                         else if (ent == r_refdef.scene.worldentity)
10073                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10074                                         else
10075                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10076                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
10077                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
10078                                         R_Mesh_ColorPointer(NULL, 0, 0);
10079                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
10080                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10081                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
10082                                         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);
10083                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10084                                         CHECKGLERROR
10085                                 }
10086                                 if (r_shownormals.value < 0)
10087                                 {
10088                                         qglBegin(GL_LINES);
10089                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10090                                         {
10091                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10092                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10093                                                 qglVertex3f(v[0], v[1], v[2]);
10094                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
10095                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10096                                                 qglVertex3f(v[0], v[1], v[2]);
10097                                         }
10098                                         qglEnd();
10099                                         CHECKGLERROR
10100                                 }
10101                                 if (r_shownormals.value > 0)
10102                                 {
10103                                         qglBegin(GL_LINES);
10104                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10105                                         {
10106                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10107                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10108                                                 qglVertex3f(v[0], v[1], v[2]);
10109                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
10110                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10111                                                 qglVertex3f(v[0], v[1], v[2]);
10112                                         }
10113                                         qglEnd();
10114                                         CHECKGLERROR
10115                                         qglBegin(GL_LINES);
10116                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10117                                         {
10118                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10119                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10120                                                 qglVertex3f(v[0], v[1], v[2]);
10121                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
10122                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10123                                                 qglVertex3f(v[0], v[1], v[2]);
10124                                         }
10125                                         qglEnd();
10126                                         CHECKGLERROR
10127                                         qglBegin(GL_LINES);
10128                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10129                                         {
10130                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10131                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10132                                                 qglVertex3f(v[0], v[1], v[2]);
10133                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
10134                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10135                                                 qglVertex3f(v[0], v[1], v[2]);
10136                                         }
10137                                         qglEnd();
10138                                         CHECKGLERROR
10139                                 }
10140                         }
10141                 }
10142                 rsurface.texture = NULL;
10143         }
10144 }
10145
10146 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10147 int r_maxsurfacelist = 0;
10148 const msurface_t **r_surfacelist = NULL;
10149 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10150 {
10151         int i, j, endj, f, flagsmask;
10152         texture_t *t;
10153         dp_model_t *model = r_refdef.scene.worldmodel;
10154         msurface_t *surfaces;
10155         unsigned char *update;
10156         int numsurfacelist = 0;
10157         if (model == NULL)
10158                 return;
10159
10160         if (r_maxsurfacelist < model->num_surfaces)
10161         {
10162                 r_maxsurfacelist = model->num_surfaces;
10163                 if (r_surfacelist)
10164                         Mem_Free((msurface_t**)r_surfacelist);
10165                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10166         }
10167
10168         RSurf_ActiveWorldEntity();
10169
10170         surfaces = model->data_surfaces;
10171         update = model->brushq1.lightmapupdateflags;
10172
10173         // update light styles on this submodel
10174         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
10175         {
10176                 model_brush_lightstyleinfo_t *style;
10177                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10178                 {
10179                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
10180                         {
10181                                 int *list = style->surfacelist;
10182                                 style->value = r_refdef.scene.lightstylevalue[style->style];
10183                                 for (j = 0;j < style->numsurfaces;j++)
10184                                         update[list[j]] = true;
10185                         }
10186                 }
10187         }
10188
10189         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10190
10191         if (debug)
10192         {
10193                 R_DrawDebugModel();
10194                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10195                 return;
10196         }
10197
10198         f = 0;
10199         t = NULL;
10200         rsurface.uselightmaptexture = false;
10201         rsurface.texture = NULL;
10202         rsurface.rtlight = NULL;
10203         numsurfacelist = 0;
10204         // add visible surfaces to draw list
10205         for (i = 0;i < model->nummodelsurfaces;i++)
10206         {
10207                 j = model->sortedmodelsurfaces[i];
10208                 if (r_refdef.viewcache.world_surfacevisible[j])
10209                         r_surfacelist[numsurfacelist++] = surfaces + j;
10210         }
10211         // update lightmaps if needed
10212         if (update)
10213         {
10214                 int updated = 0;
10215                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10216                 {
10217                         if (r_refdef.viewcache.world_surfacevisible[j])
10218                         {
10219                                 if (update[j])
10220                                 {
10221                                         updated++;
10222                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
10223                                 }
10224                         }
10225                 }
10226                 if (updated)
10227                 {
10228                         int count = model->brushq3.num_mergedlightmaps;
10229                         for (i = 0;i < count;i++)
10230                         {
10231                                 if (model->brushq3.data_deluxemaps[i])
10232                                         R_FlushTexture(model->brushq3.data_deluxemaps[i]);
10233                                 if (model->brushq3.data_lightmaps[i])
10234                                         R_FlushTexture(model->brushq3.data_lightmaps[i]);
10235                         }
10236                 }
10237         }
10238         // don't do anything if there were no surfaces
10239         if (!numsurfacelist)
10240         {
10241                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10242                 return;
10243         }
10244         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
10245         GL_AlphaTest(false);
10246
10247         // add to stats if desired
10248         if (r_speeds.integer && !skysurfaces && !depthonly)
10249         {
10250                 r_refdef.stats.world_surfaces += numsurfacelist;
10251                 for (j = 0;j < numsurfacelist;j++)
10252                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
10253         }
10254
10255         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10256 }
10257
10258 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10259 {
10260         int i, j, endj, f, flagsmask;
10261         texture_t *t;
10262         dp_model_t *model = ent->model;
10263         msurface_t *surfaces;
10264         unsigned char *update;
10265         int numsurfacelist = 0;
10266         if (model == NULL)
10267                 return;
10268
10269         if (r_maxsurfacelist < model->num_surfaces)
10270         {
10271                 r_maxsurfacelist = model->num_surfaces;
10272                 if (r_surfacelist)
10273                         Mem_Free((msurface_t **)r_surfacelist);
10274                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10275         }
10276
10277         // if the model is static it doesn't matter what value we give for
10278         // wantnormals and wanttangents, so this logic uses only rules applicable
10279         // to a model, knowing that they are meaningless otherwise
10280         if (ent == r_refdef.scene.worldentity)
10281                 RSurf_ActiveWorldEntity();
10282         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10283                 RSurf_ActiveModelEntity(ent, false, false, false);
10284         else if (prepass)
10285                 RSurf_ActiveModelEntity(ent, true, true, true);
10286         else if (depthonly)
10287                 RSurf_ActiveModelEntity(ent, false, false, false);
10288         else
10289         {
10290                 switch (vid.renderpath)
10291                 {
10292                 case RENDERPATH_GL20:
10293                 case RENDERPATH_CGGL:
10294                         RSurf_ActiveModelEntity(ent, true, true, false);
10295                         break;
10296                 case RENDERPATH_GL13:
10297                 case RENDERPATH_GL11:
10298                         RSurf_ActiveModelEntity(ent, true, false, false);
10299                         break;
10300                 }
10301         }
10302
10303         surfaces = model->data_surfaces;
10304         update = model->brushq1.lightmapupdateflags;
10305
10306         // update light styles
10307         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
10308         {
10309                 model_brush_lightstyleinfo_t *style;
10310                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10311                 {
10312                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
10313                         {
10314                                 int *list = style->surfacelist;
10315                                 style->value = r_refdef.scene.lightstylevalue[style->style];
10316                                 for (j = 0;j < style->numsurfaces;j++)
10317                                         update[list[j]] = true;
10318                         }
10319                 }
10320         }
10321
10322         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10323
10324         if (debug)
10325         {
10326                 R_DrawDebugModel();
10327                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10328                 return;
10329         }
10330
10331         f = 0;
10332         t = NULL;
10333         rsurface.uselightmaptexture = false;
10334         rsurface.texture = NULL;
10335         rsurface.rtlight = NULL;
10336         numsurfacelist = 0;
10337         // add visible surfaces to draw list
10338         for (i = 0;i < model->nummodelsurfaces;i++)
10339                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
10340         // don't do anything if there were no surfaces
10341         if (!numsurfacelist)
10342         {
10343                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10344                 return;
10345         }
10346         // update lightmaps if needed
10347         if (update)
10348         {
10349                 int updated = 0;
10350                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10351                 {
10352                         if (update[j])
10353                         {
10354                                 updated++;
10355                                 R_BuildLightMap(ent, surfaces + j);
10356                         }
10357                 }
10358                 if (updated)
10359                 {
10360                         int count = model->brushq3.num_mergedlightmaps;
10361                         for (i = 0;i < count;i++)
10362                         {
10363                                 if (model->brushq3.data_deluxemaps[i])
10364                                         R_FlushTexture(model->brushq3.data_deluxemaps[i]);
10365                                 if (model->brushq3.data_lightmaps[i])
10366                                         R_FlushTexture(model->brushq3.data_lightmaps[i]);
10367                         }
10368                 }
10369         }
10370         if (update)
10371                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10372                         if (update[j])
10373                                 R_BuildLightMap(ent, surfaces + j);
10374         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
10375         GL_AlphaTest(false);
10376
10377         // add to stats if desired
10378         if (r_speeds.integer && !skysurfaces && !depthonly)
10379         {
10380                 r_refdef.stats.entities_surfaces += numsurfacelist;
10381                 for (j = 0;j < numsurfacelist;j++)
10382                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
10383         }
10384
10385         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10386 }
10387
10388 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
10389 {
10390         static texture_t texture;
10391         static msurface_t surface;
10392         const msurface_t *surfacelist = &surface;
10393
10394         // fake enough texture and surface state to render this geometry
10395
10396         texture.update_lastrenderframe = -1; // regenerate this texture
10397         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
10398         texture.currentskinframe = skinframe;
10399         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
10400         texture.specularscalemod = 1;
10401         texture.specularpowermod = 1;
10402
10403         surface.texture = &texture;
10404         surface.num_triangles = numtriangles;
10405         surface.num_firsttriangle = firsttriangle;
10406         surface.num_vertices = numvertices;
10407         surface.num_firstvertex = firstvertex;
10408
10409         // now render it
10410         rsurface.texture = R_GetCurrentTexture(surface.texture);
10411         rsurface.uselightmaptexture = false;
10412         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10413 }
10414
10415 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)
10416 {
10417         static msurface_t surface;
10418         const msurface_t *surfacelist = &surface;
10419
10420         // fake enough texture and surface state to render this geometry
10421
10422         surface.texture = texture;
10423         surface.num_triangles = numtriangles;
10424         surface.num_firsttriangle = firsttriangle;
10425         surface.num_vertices = numvertices;
10426         surface.num_firstvertex = firstvertex;
10427
10428         // now render it
10429         rsurface.texture = R_GetCurrentTexture(surface.texture);
10430         rsurface.uselightmaptexture = false;
10431         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10432 }