]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
the beginnings of a cgGL rendering path experiment, does not work yet
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
30
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
32
33 qboolean r_loadnormalmap;
34 qboolean r_loadgloss;
35 qboolean r_loadfog;
36
37 //
38 // screen size info
39 //
40 r_refdef_t r_refdef;
41
42 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
43 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
44 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
45 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
46 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
47 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
48 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
49 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
50
51 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
52 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
53 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
54 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
55 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
56
57 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
58 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
59 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
60 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
61 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
62 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
63 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
64 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
65 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
66 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
67 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
68 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
69 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
70 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
71 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
72 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
73 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
74 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
75 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
76 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
77 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
78 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
79 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
80 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
81 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
82 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
83 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
84 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
85 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
86 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
87 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
88 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
89 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
90 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
91 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
92 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
93 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
94 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
95 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
96 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
97 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
98 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
99
100 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
101 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
102 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
103 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
104 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
105 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
106 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
107 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
108
109 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
110 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
111 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
112
113 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
114 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
115 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
116 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
117 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
118 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
119 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
120 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
121 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
122
123 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
124 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
125 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
126 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
127 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
128
129 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
130 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
131 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
132 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
133
134 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
135 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
136 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
137 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
138 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
139 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
140 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
141
142 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
143 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
144 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
145 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
146
147 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
148
149 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
150
151 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
152
153 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
154 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
155 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
156 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
157 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
158 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
159 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
160
161 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
162
163 extern cvar_t v_glslgamma;
164
165 extern qboolean v_flipped_state;
166
167 static struct r_bloomstate_s
168 {
169         qboolean enabled;
170         qboolean hdr;
171
172         int bloomwidth, bloomheight;
173
174         int screentexturewidth, screentextureheight;
175         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
176
177         int bloomtexturewidth, bloomtextureheight;
178         rtexture_t *texture_bloom;
179
180         // arrays for rendering the screen passes
181         float screentexcoord2f[8];
182         float bloomtexcoord2f[8];
183         float offsettexcoord2f[8];
184
185         r_viewport_t viewport;
186 }
187 r_bloomstate;
188
189 r_waterstate_t r_waterstate;
190
191 /// shadow volume bsp struct with automatically growing nodes buffer
192 svbsp_t r_svbsp;
193
194 rtexture_t *r_texture_blanknormalmap;
195 rtexture_t *r_texture_white;
196 rtexture_t *r_texture_grey128;
197 rtexture_t *r_texture_black;
198 rtexture_t *r_texture_notexture;
199 rtexture_t *r_texture_whitecube;
200 rtexture_t *r_texture_normalizationcube;
201 rtexture_t *r_texture_fogattenuation;
202 rtexture_t *r_texture_gammaramps;
203 unsigned int r_texture_gammaramps_serial;
204 //rtexture_t *r_texture_fogintensity;
205
206 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
207 unsigned int r_numqueries;
208 unsigned int r_maxqueries;
209
210 typedef struct r_qwskincache_s
211 {
212         char name[MAX_QPATH];
213         skinframe_t *skinframe;
214 }
215 r_qwskincache_t;
216
217 static r_qwskincache_t *r_qwskincache;
218 static int r_qwskincache_size;
219
220 /// vertex coordinates for a quad that covers the screen exactly
221 const float r_screenvertex3f[12] =
222 {
223         0, 0, 0,
224         1, 0, 0,
225         1, 1, 0,
226         0, 1, 0
227 };
228
229 extern void R_DrawModelShadows(void);
230
231 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
232 {
233         int i;
234         for (i = 0;i < verts;i++)
235         {
236                 out[0] = in[0] * r;
237                 out[1] = in[1] * g;
238                 out[2] = in[2] * b;
239                 out[3] = in[3];
240                 in += 4;
241                 out += 4;
242         }
243 }
244
245 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
246 {
247         int i;
248         for (i = 0;i < verts;i++)
249         {
250                 out[0] = r;
251                 out[1] = g;
252                 out[2] = b;
253                 out[3] = a;
254                 out += 4;
255         }
256 }
257
258 // FIXME: move this to client?
259 void FOG_clear(void)
260 {
261         if (gamemode == GAME_NEHAHRA)
262         {
263                 Cvar_Set("gl_fogenable", "0");
264                 Cvar_Set("gl_fogdensity", "0.2");
265                 Cvar_Set("gl_fogred", "0.3");
266                 Cvar_Set("gl_foggreen", "0.3");
267                 Cvar_Set("gl_fogblue", "0.3");
268         }
269         r_refdef.fog_density = 0;
270         r_refdef.fog_red = 0;
271         r_refdef.fog_green = 0;
272         r_refdef.fog_blue = 0;
273         r_refdef.fog_alpha = 1;
274         r_refdef.fog_start = 0;
275         r_refdef.fog_end = 16384;
276         r_refdef.fog_height = 1<<30;
277         r_refdef.fog_fadedepth = 128;
278 }
279
280 static void R_BuildBlankTextures(void)
281 {
282         unsigned char data[4];
283         data[2] = 128; // normal X
284         data[1] = 128; // normal Y
285         data[0] = 255; // normal Z
286         data[3] = 128; // height
287         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
288         data[0] = 255;
289         data[1] = 255;
290         data[2] = 255;
291         data[3] = 255;
292         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
293         data[0] = 128;
294         data[1] = 128;
295         data[2] = 128;
296         data[3] = 255;
297         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
298         data[0] = 0;
299         data[1] = 0;
300         data[2] = 0;
301         data[3] = 255;
302         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
303 }
304
305 static void R_BuildNoTexture(void)
306 {
307         int x, y;
308         unsigned char pix[16][16][4];
309         // this makes a light grey/dark grey checkerboard texture
310         for (y = 0;y < 16;y++)
311         {
312                 for (x = 0;x < 16;x++)
313                 {
314                         if ((y < 8) ^ (x < 8))
315                         {
316                                 pix[y][x][0] = 128;
317                                 pix[y][x][1] = 128;
318                                 pix[y][x][2] = 128;
319                                 pix[y][x][3] = 255;
320                         }
321                         else
322                         {
323                                 pix[y][x][0] = 64;
324                                 pix[y][x][1] = 64;
325                                 pix[y][x][2] = 64;
326                                 pix[y][x][3] = 255;
327                         }
328                 }
329         }
330         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
331 }
332
333 static void R_BuildWhiteCube(void)
334 {
335         unsigned char data[6*1*1*4];
336         memset(data, 255, sizeof(data));
337         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
338 }
339
340 static void R_BuildNormalizationCube(void)
341 {
342         int x, y, side;
343         vec3_t v;
344         vec_t s, t, intensity;
345 #define NORMSIZE 64
346         unsigned char *data;
347         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
348         for (side = 0;side < 6;side++)
349         {
350                 for (y = 0;y < NORMSIZE;y++)
351                 {
352                         for (x = 0;x < NORMSIZE;x++)
353                         {
354                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
355                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
356                                 switch(side)
357                                 {
358                                 default:
359                                 case 0:
360                                         v[0] = 1;
361                                         v[1] = -t;
362                                         v[2] = -s;
363                                         break;
364                                 case 1:
365                                         v[0] = -1;
366                                         v[1] = -t;
367                                         v[2] = s;
368                                         break;
369                                 case 2:
370                                         v[0] = s;
371                                         v[1] = 1;
372                                         v[2] = t;
373                                         break;
374                                 case 3:
375                                         v[0] = s;
376                                         v[1] = -1;
377                                         v[2] = -t;
378                                         break;
379                                 case 4:
380                                         v[0] = s;
381                                         v[1] = -t;
382                                         v[2] = 1;
383                                         break;
384                                 case 5:
385                                         v[0] = -s;
386                                         v[1] = -t;
387                                         v[2] = -1;
388                                         break;
389                                 }
390                                 intensity = 127.0f / sqrt(DotProduct(v, v));
391                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
392                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
393                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
394                                 data[((side*64+y)*64+x)*4+3] = 255;
395                         }
396                 }
397         }
398         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
399         Mem_Free(data);
400 }
401
402 static void R_BuildFogTexture(void)
403 {
404         int x, b;
405 #define FOGWIDTH 256
406         unsigned char data1[FOGWIDTH][4];
407         //unsigned char data2[FOGWIDTH][4];
408         double d, r, alpha;
409
410         r_refdef.fogmasktable_start = r_refdef.fog_start;
411         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
412         r_refdef.fogmasktable_range = r_refdef.fogrange;
413         r_refdef.fogmasktable_density = r_refdef.fog_density;
414
415         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
416         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
417         {
418                 d = (x * r - r_refdef.fogmasktable_start);
419                 if(developer.integer >= 100)
420                         Con_Printf("%f ", d);
421                 d = max(0, d);
422                 if (r_fog_exp2.integer)
423                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
424                 else
425                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
426                 if(developer.integer >= 100)
427                         Con_Printf(" : %f ", alpha);
428                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
429                 if(developer.integer >= 100)
430                         Con_Printf(" = %f\n", alpha);
431                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
432         }
433
434         for (x = 0;x < FOGWIDTH;x++)
435         {
436                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
437                 data1[x][0] = b;
438                 data1[x][1] = b;
439                 data1[x][2] = b;
440                 data1[x][3] = 255;
441                 //data2[x][0] = 255 - b;
442                 //data2[x][1] = 255 - b;
443                 //data2[x][2] = 255 - b;
444                 //data2[x][3] = 255;
445         }
446         if (r_texture_fogattenuation)
447         {
448                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
449                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
450         }
451         else
452         {
453                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
454                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
455         }
456 }
457
458 static const char *builtinshaderstring =
459 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
460 "// written by Forest 'LordHavoc' Hale\n"
461 "\n"
462 "// enable various extensions depending on permutation:\n"
463 "\n"
464 "#ifdef VERTEX_SHADER\n"
465 "uniform mat4 ModelViewProjectionMatrix;\n"
466 "#endif\n"
467 "\n"
468 "#ifdef MODE_DEPTH_OR_SHADOW\n"
469 "#ifdef VERTEX_SHADER\n"
470 "void main(void)\n"
471 "{\n"
472 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
473 "}\n"
474 "#endif\n"
475 "#else // !MODE_DEPTH_ORSHADOW\n"
476 "#ifdef MODE_SHOWDEPTH\n"
477 "#ifdef VERTEX_SHADER\n"
478 "void main(void)\n"
479 "{\n"
480 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
481 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
482 "}\n"
483 "#endif\n"
484 "\n"
485 "#ifdef FRAGMENT_SHADER\n"
486 "void main(void)\n"
487 "{\n"
488 "       gl_FragColor = gl_Color;\n"
489 "}\n"
490 "#endif\n"
491 "#else // !MODE_SHOWDEPTH\n"
492 "#ifdef MODE_POSTPROCESS\n"
493 "varying vec2 TexCoord1;\n"
494 "varying vec2 TexCoord2;\n"
495 "\n"
496 "#ifdef VERTEX_SHADER\n"
497 "void main(void)\n"
498 "{\n"
499 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
500 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
501 "#ifdef USEBLOOM\n"
502 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
503 "#endif\n"
504 "}\n"
505 "#endif\n"
506 "\n"
507 "#ifdef FRAGMENT_SHADER\n"
508 "uniform sampler2D Texture_First;\n"
509 "#ifdef USEBLOOM\n"
510 "uniform sampler2D Texture_Second;\n"
511 "#endif\n"
512 "#ifdef USEGAMMARAMPS\n"
513 "uniform sampler2D Texture_GammaRamps;\n"
514 "#endif\n"
515 "#ifdef USESATURATION\n"
516 "uniform float Saturation;\n"
517 "#endif\n"
518 "#ifdef USEVIEWTINT\n"
519 "uniform vec4 ViewTintColor;\n"
520 "#endif\n"
521 "//uncomment these if you want to use them:\n"
522 "uniform vec4 UserVec1;\n"
523 "// uniform vec4 UserVec2;\n"
524 "// uniform vec4 UserVec3;\n"
525 "// uniform vec4 UserVec4;\n"
526 "// uniform float ClientTime;\n"
527 "uniform vec2 PixelSize;\n"
528 "void main(void)\n"
529 "{\n"
530 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
531 "#ifdef USEBLOOM\n"
532 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
533 "#endif\n"
534 "#ifdef USEVIEWTINT\n"
535 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
536 "#endif\n"
537 "\n"
538 "#ifdef USEPOSTPROCESSING\n"
539 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
540 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
541 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
542 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
543 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
544 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
545 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
546 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
547 "#endif\n"
548 "\n"
549 "#ifdef USESATURATION\n"
550 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
551 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
552 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
553 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
554 "#endif\n"
555 "\n"
556 "#ifdef USEGAMMARAMPS\n"
557 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
558 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
559 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
560 "#endif\n"
561 "}\n"
562 "#endif\n"
563 "#else // !MODE_POSTPROCESS\n"
564 "#ifdef MODE_GENERIC\n"
565 "#ifdef USEDIFFUSE\n"
566 "varying vec2 TexCoord1;\n"
567 "#endif\n"
568 "#ifdef USESPECULAR\n"
569 "varying vec2 TexCoord2;\n"
570 "#endif\n"
571 "#ifdef VERTEX_SHADER\n"
572 "void main(void)\n"
573 "{\n"
574 "       gl_FrontColor = gl_Color;\n"
575 "#ifdef USEDIFFUSE\n"
576 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
577 "#endif\n"
578 "#ifdef USESPECULAR\n"
579 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
580 "#endif\n"
581 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
582 "}\n"
583 "#endif\n"
584 "\n"
585 "#ifdef FRAGMENT_SHADER\n"
586 "#ifdef USEDIFFUSE\n"
587 "uniform sampler2D Texture_First;\n"
588 "#endif\n"
589 "#ifdef USESPECULAR\n"
590 "uniform sampler2D Texture_Second;\n"
591 "#endif\n"
592 "\n"
593 "void main(void)\n"
594 "{\n"
595 "       gl_FragColor = gl_Color;\n"
596 "#ifdef USEDIFFUSE\n"
597 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
598 "#endif\n"
599 "\n"
600 "#ifdef USESPECULAR\n"
601 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
602 "# ifdef USECOLORMAPPING\n"
603 "       gl_FragColor *= tex2;\n"
604 "# endif\n"
605 "# ifdef USEGLOW\n"
606 "       gl_FragColor += tex2;\n"
607 "# endif\n"
608 "# ifdef USEVERTEXTEXTUREBLEND\n"
609 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
610 "# endif\n"
611 "#endif\n"
612 "}\n"
613 "#endif\n"
614 "#else // !MODE_GENERIC\n"
615 "#ifdef MODE_BLOOMBLUR\n"
616 "varying TexCoord;\n"
617 "#ifdef VERTEX_SHADER\n"
618 "void main(void)\n"
619 "{\n"
620 "       gl_FrontColor = gl_Color;\n"
621 "       TexCoord = gl_MultiTexCoord0.xy;\n"
622 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
623 "}\n"
624 "#endif\n"
625 "\n"
626 "#ifdef FRAGMENT_SHADER\n"
627 "uniform sampler2D Texture_First;\n"
628 "uniform vec4 BloomBlur_Parameters;\n"
629 "\n"
630 "void main(void)\n"
631 "{\n"
632 "       int i;\n"
633 "       vec2 tc = TexCoord;\n"
634 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
635 "       tc += BloomBlur_Parameters.xy;\n"
636 "       for (i = 1;i < SAMPLES;i++)\n"
637 "       {\n"
638 "               color += texture2D(Texture_First, tc).rgb;\n"
639 "               tc += BloomBlur_Parameters.xy;\n"
640 "       }\n"
641 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
642 "}\n"
643 "#endif\n"
644 "#else // !MODE_BLOOMBLUR\n"
645 "#ifdef MODE_REFRACTION\n"
646 "varying vec2 TexCoord;\n"
647 "varying vec4 ModelViewProjectionPosition;\n"
648 "uniform mat4 TexMatrix;\n"
649 "#ifdef VERTEX_SHADER\n"
650 "\n"
651 "void main(void)\n"
652 "{\n"
653 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
654 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
655 "       ModelViewProjectionPosition = gl_Position;\n"
656 "}\n"
657 "#endif\n"
658 "\n"
659 "#ifdef FRAGMENT_SHADER\n"
660 "uniform sampler2D Texture_Normal;\n"
661 "uniform sampler2D Texture_Refraction;\n"
662 "uniform sampler2D Texture_Reflection;\n"
663 "\n"
664 "uniform vec4 DistortScaleRefractReflect;\n"
665 "uniform vec4 ScreenScaleRefractReflect;\n"
666 "uniform vec4 ScreenCenterRefractReflect;\n"
667 "uniform vec4 RefractColor;\n"
668 "uniform vec4 ReflectColor;\n"
669 "uniform float ReflectFactor;\n"
670 "uniform float ReflectOffset;\n"
671 "\n"
672 "void main(void)\n"
673 "{\n"
674 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
675 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
676 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
677 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
678 "       // FIXME temporary hack to detect the case that the reflection\n"
679 "       // gets blackened at edges due to leaving the area that contains actual\n"
680 "       // content.\n"
681 "       // Remove this 'ack once we have a better way to stop this thing from\n"
682 "       // 'appening.\n"
683 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
684 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
685 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
686 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
687 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
688 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
689 "}\n"
690 "#endif\n"
691 "#else // !MODE_REFRACTION\n"
692 "#ifdef MODE_WATER\n"
693 "varying vec2 TexCoord;\n"
694 "varying vec3 EyeVector;\n"
695 "varying vec4 ModelViewProjectionPosition;\n"
696 "#ifdef VERTEX_SHADER\n"
697 "uniform vec3 EyePosition;\n"
698 "uniform mat4 TexMatrix;\n"
699 "\n"
700 "void main(void)\n"
701 "{\n"
702 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
703 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
704 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
705 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
706 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
707 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
708 "       ModelViewProjectionPosition = gl_Position;\n"
709 "}\n"
710 "#endif\n"
711 "\n"
712 "#ifdef FRAGMENT_SHADER\n"
713 "uniform sampler2D Texture_Normal;\n"
714 "uniform sampler2D Texture_Refraction;\n"
715 "uniform sampler2D Texture_Reflection;\n"
716 "\n"
717 "uniform vec4 DistortScaleRefractReflect;\n"
718 "uniform vec4 ScreenScaleRefractReflect;\n"
719 "uniform vec4 ScreenCenterRefractReflect;\n"
720 "uniform vec4 RefractColor;\n"
721 "uniform vec4 ReflectColor;\n"
722 "uniform float ReflectFactor;\n"
723 "uniform float ReflectOffset;\n"
724 "\n"
725 "void main(void)\n"
726 "{\n"
727 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
728 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
729 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
730 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
731 "       // FIXME temporary hack to detect the case that the reflection\n"
732 "       // gets blackened at edges due to leaving the area that contains actual\n"
733 "       // content.\n"
734 "       // Remove this 'ack once we have a better way to stop this thing from\n"
735 "       // 'appening.\n"
736 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
737 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
738 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
739 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
740 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
741 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
742 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
743 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
744 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
745 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
746 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
747 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
748 "}\n"
749 "#endif\n"
750 "#else // !MODE_WATER\n"
751 "\n"
752 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
753 "# extension GL_ARB_texture_rectangle : enable\n"
754 "#endif\n"
755 "\n"
756 "#ifdef USESHADOWMAP2D\n"
757 "# ifdef GL_EXT_gpu_shader4\n"
758 "#   extension GL_EXT_gpu_shader4 : enable\n"
759 "# endif\n"
760 "# ifdef GL_ARB_texture_gather\n"
761 "#   extension GL_ARB_texture_gather : enable\n"
762 "# else\n"
763 "#   ifdef GL_AMD_texture_texture4\n"
764 "#     extension GL_AMD_texture_texture4 : enable\n"
765 "#   endif\n"
766 "# endif\n"
767 "#endif\n"
768 "\n"
769 "#ifdef USESHADOWMAPCUBE\n"
770 "# extension GL_EXT_gpu_shader4 : enable\n"
771 "#endif\n"
772 "\n"
773 "#ifdef USESHADOWSAMPLER\n"
774 "# extension GL_ARB_shadow : enable\n"
775 "#endif\n"
776 "\n"
777 "// common definitions between vertex shader and fragment shader:\n"
778 "\n"
779 "//#ifdef __GLSL_CG_DATA_TYPES\n"
780 "//# define myhalf half\n"
781 "//# define myhalf2 half2\n"
782 "//# define myhalf3half3\n"
783 "//# define myhalf4 half4\n"
784 "//#else\n"
785 "# define myhalf float\n"
786 "# define myhalf2 vec2\n"
787 "# define myhalf3 vec3\n"
788 "# define myhalf4 vec4\n"
789 "//#endif\n"
790 "\n"
791 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
792 "# define USEFOG\n"
793 "#endif\n"
794 "\n"
795 "varying vec2 TexCoord;\n"
796 "#ifdef USEVERTEXTEXTUREBLEND\n"
797 "varying vec2 TexCoord2;\n"
798 "#endif\n"
799 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
800 "#define USELIGHTMAP\n"
801 "varying vec2 TexCoordLightmap;\n"
802 "#endif\n"
803 "\n"
804 "#ifdef MODE_LIGHTSOURCE\n"
805 "varying vec3 CubeVector;\n"
806 "#endif\n"
807 "\n"
808 "#ifdef MODE_LIGHTSOURCE\n"
809 "varying vec3 LightVector;\n"
810 "#endif\n"
811 "#if defined(MODE_LIGHTDIRECTION)\n"
812 "varying vec3 LightVector;\n"
813 "#endif\n"
814 "\n"
815 "#if defined(USEOFFSETMAPPING) || defined(USESPECULAR)\n"
816 "//#if defined(USEOFFSETMAPPING) || defined(USESPECULAR) || defined(MODE_LIGHTDIRECTION) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
817 "#define USEEYEVECTOR\n"
818 "varying vec3 EyeVector;\n"
819 "#endif\n"
820 "#ifdef USEFOG\n"
821 "varying vec3 EyeVectorModelSpace;\n"
822 "varying float FogPlaneVertexDist;\n"
823 "#endif\n"
824 "\n"
825 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
826 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
827 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
828 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
829 "#endif\n"
830 "\n"
831 "#ifdef USEREFLECTION\n"
832 "varying vec4 ModelViewProjectionPosition;\n"
833 "#endif\n"
834 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
835 "uniform vec3 LightPosition;\n"
836 "varying vec4 ModelViewPosition;\n"
837 "#endif\n"
838 "\n"
839 "#ifdef MODE_LIGHTSOURCE\n"
840 "uniform vec3 LightPosition;\n"
841 "#endif\n"
842 "uniform vec3 EyePosition;\n"
843 "#ifdef MODE_LIGHTDIRECTION\n"
844 "uniform vec3 LightDir;\n"
845 "#endif\n"
846 "uniform vec4 FogPlane;\n"
847 "\n"
848 "\n"
849 "\n"
850 "\n"
851 "\n"
852 "// vertex shader specific:\n"
853 "#ifdef VERTEX_SHADER\n"
854 "\n"
855 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
856 "\n"
857 "#ifdef MODE_DEFERREDGEOMETRY\n"
858 "uniform mat4 TexMatrix;\n"
859 "#ifdef USEVERTEXTEXTUREBLEND\n"
860 "uniform mat4 BackgroundTexMatrix;\n"
861 "#endif\n"
862 "uniform mat4 ModelViewMatrix;\n"
863 "void main(void)\n"
864 "{\n"
865 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
866 "#ifdef USEVERTEXTEXTUREBLEND\n"
867 "       gl_FrontColor = gl_Color;\n"
868 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
869 "#endif\n"
870 "\n"
871 "       // transform unnormalized eye direction into tangent space\n"
872 "#ifdef USEOFFSETMAPPING\n"
873 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
874 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
875 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
876 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
877 "#endif\n"
878 "\n"
879 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
880 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
881 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
882 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
883 "}\n"
884 "#else // !MODE_DEFERREDGEOMETRY\n"
885 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
886 "uniform mat4 ModelViewMatrix;\n"
887 "void main(void)\n"
888 "{\n"
889 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
890 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
891 "}\n"
892 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
893 "uniform mat4 TexMatrix;\n"
894 "#ifdef USEVERTEXTEXTUREBLEND\n"
895 "uniform mat4 BackgroundTexMatrix;\n"
896 "#endif\n"
897 "#ifdef MODE_LIGHTSOURCE\n"
898 "uniform mat4 ModelToLight;\n"
899 "#endif\n"
900 "void main(void)\n"
901 "{\n"
902 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
903 "       gl_FrontColor = gl_Color;\n"
904 "#endif\n"
905 "       // copy the surface texcoord\n"
906 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
907 "#ifdef USEVERTEXTEXTUREBLEND\n"
908 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
909 "#endif\n"
910 "#ifdef USELIGHTMAP\n"
911 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
912 "#endif\n"
913 "\n"
914 "#ifdef MODE_LIGHTSOURCE\n"
915 "       // transform vertex position into light attenuation/cubemap space\n"
916 "       // (-1 to +1 across the light box)\n"
917 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
918 "\n"
919 "# ifdef USEDIFFUSE\n"
920 "       // transform unnormalized light direction into tangent space\n"
921 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
922 "       //  normalize it per pixel)\n"
923 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
924 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
925 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
926 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
927 "# endif\n"
928 "#endif\n"
929 "\n"
930 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
931 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
932 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
933 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
934 "#endif\n"
935 "\n"
936 "       // transform unnormalized eye direction into tangent space\n"
937 "#ifdef USEEYEVECTOR\n"
938 "#ifndef USEFOG\n"
939 "       vec3 EyeVectorModelSpace;\n"
940 "#endif\n"
941 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
942 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
943 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
944 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
945 "#endif\n"
946 "\n"
947 "#ifdef USEFOG\n"
948 "#ifndef USEEYEVECTOR\n"
949 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
950 "#endif\n"
951 "       FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
952 "#endif\n"
953 "\n"
954 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
955 "       VectorS = gl_MultiTexCoord1.xyz;\n"
956 "       VectorT = gl_MultiTexCoord2.xyz;\n"
957 "       VectorR = gl_MultiTexCoord3.xyz;\n"
958 "#endif\n"
959 "\n"
960 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
961 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
962 "\n"
963 "#ifdef USEREFLECTION\n"
964 "       ModelViewProjectionPosition = gl_Position;\n"
965 "#endif\n"
966 "}\n"
967 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
968 "#endif // !MODE_DEFERREDGEOMETRY\n"
969 "\n"
970 "#endif // VERTEX_SHADER\n"
971 "\n"
972 "\n"
973 "\n"
974 "\n"
975 "// fragment shader specific:\n"
976 "#ifdef FRAGMENT_SHADER\n"
977 "\n"
978 "uniform sampler2D Texture_Normal;\n"
979 "uniform sampler2D Texture_Color;\n"
980 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
981 "uniform sampler2D Texture_Gloss;\n"
982 "//#endif\n"
983 "#ifdef USEGLOW\n"
984 "uniform sampler2D Texture_Glow;\n"
985 "#endif\n"
986 "#ifdef USEVERTEXTEXTUREBLEND\n"
987 "uniform sampler2D Texture_SecondaryNormal;\n"
988 "uniform sampler2D Texture_SecondaryColor;\n"
989 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
990 "uniform sampler2D Texture_SecondaryGloss;\n"
991 "//#endif\n"
992 "#ifdef USEGLOW\n"
993 "uniform sampler2D Texture_SecondaryGlow;\n"
994 "#endif\n"
995 "#endif\n"
996 "#ifdef USECOLORMAPPING\n"
997 "uniform sampler2D Texture_Pants;\n"
998 "uniform sampler2D Texture_Shirt;\n"
999 "#endif\n"
1000 "#ifdef USEFOG\n"
1001 "uniform sampler2D Texture_FogMask;\n"
1002 "#endif\n"
1003 "#ifdef USELIGHTMAP\n"
1004 "uniform sampler2D Texture_Lightmap;\n"
1005 "#endif\n"
1006 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1007 "uniform sampler2D Texture_Deluxemap;\n"
1008 "#endif\n"
1009 "#ifdef USEREFLECTION\n"
1010 "uniform sampler2D Texture_Reflection;\n"
1011 "#endif\n"
1012 "\n"
1013 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1014 "uniform sampler2DRect Texture_ScreenDepth;\n"
1015 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
1016 "#endif\n"
1017 "#ifdef USEDEFERREDLIGHTMAP\n"
1018 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
1019 "uniform sampler2DRect Texture_ScreenSpecular;\n"
1020 "#endif\n"
1021 "\n"
1022 "uniform myhalf3 Color_Pants;\n"
1023 "uniform myhalf3 Color_Shirt;\n"
1024 "uniform myhalf3 FogColor;\n"
1025 "\n"
1026 "#ifdef USEFOG\n"
1027 "uniform float FogRangeRecip;\n"
1028 "uniform float FogPlaneViewDist;\n"
1029 "uniform float FogHeightFade;\n"
1030 "myhalf FogVertex(void)\n"
1031 "{\n"
1032 "       float fogfrac;\n"
1033 "#ifdef USEFOGOUTSIDE\n"
1034 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1035 "#else\n"
1036 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1037 "#endif\n"
1038 "       return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1039 "}\n"
1040 "#endif\n"
1041 "\n"
1042 "#ifdef USEOFFSETMAPPING\n"
1043 "uniform float OffsetMapping_Scale;\n"
1044 "vec2 OffsetMapping(vec2 TexCoord)\n"
1045 "{\n"
1046 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1047 "       // 14 sample relief mapping: linear search and then binary search\n"
1048 "       // this basically steps forward a small amount repeatedly until it finds\n"
1049 "       // itself inside solid, then jitters forward and back using decreasing\n"
1050 "       // amounts to find the impact\n"
1051 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1052 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1053 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1054 "       vec3 RT = vec3(TexCoord, 1);\n"
1055 "       OffsetVector *= 0.1;\n"
1056 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1057 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1058 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1059 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1060 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1061 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1062 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1063 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1064 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1065 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1066 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1067 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1068 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1069 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1070 "       return RT.xy;\n"
1071 "#else\n"
1072 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1073 "       // this basically moves forward the full distance, and then backs up based\n"
1074 "       // on height of samples\n"
1075 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1076 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1077 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1078 "       TexCoord += OffsetVector;\n"
1079 "       OffsetVector *= 0.333;\n"
1080 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1081 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1082 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1083 "       return TexCoord;\n"
1084 "#endif\n"
1085 "}\n"
1086 "#endif // USEOFFSETMAPPING\n"
1087 "\n"
1088 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1089 "uniform sampler2D Texture_Attenuation;\n"
1090 "uniform samplerCube Texture_Cube;\n"
1091 "\n"
1092 "#ifdef USESHADOWMAPRECT\n"
1093 "# ifdef USESHADOWSAMPLER\n"
1094 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1095 "# else\n"
1096 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1097 "# endif\n"
1098 "#endif\n"
1099 "\n"
1100 "#ifdef USESHADOWMAP2D\n"
1101 "# ifdef USESHADOWSAMPLER\n"
1102 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1103 "# else\n"
1104 "uniform sampler2D Texture_ShadowMap2D;\n"
1105 "# endif\n"
1106 "#endif\n"
1107 "\n"
1108 "#ifdef USESHADOWMAPVSDCT\n"
1109 "uniform samplerCube Texture_CubeProjection;\n"
1110 "#endif\n"
1111 "\n"
1112 "#ifdef USESHADOWMAPCUBE\n"
1113 "# ifdef USESHADOWSAMPLER\n"
1114 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1115 "# else\n"
1116 "uniform samplerCube Texture_ShadowMapCube;\n"
1117 "# endif\n"
1118 "#endif\n"
1119 "\n"
1120 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1121 "uniform vec2 ShadowMap_TextureScale;\n"
1122 "uniform vec4 ShadowMap_Parameters;\n"
1123 "#endif\n"
1124 "\n"
1125 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1126 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1127 "{\n"
1128 "       vec3 adir = abs(dir);\n"
1129 "# ifndef USESHADOWMAPVSDCT\n"
1130 "       vec2 tc;\n"
1131 "       vec2 offset;\n"
1132 "       float ma;\n"
1133 "       if (adir.x > adir.y)\n"
1134 "       {\n"
1135 "               if (adir.x > adir.z) // X\n"
1136 "               {\n"
1137 "                       ma = adir.x;\n"
1138 "                       tc = dir.zy;\n"
1139 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1140 "               }\n"
1141 "               else // Z\n"
1142 "               {\n"
1143 "                       ma = adir.z;\n"
1144 "                       tc = dir.xy;\n"
1145 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1146 "               }\n"
1147 "       }\n"
1148 "       else\n"
1149 "       {\n"
1150 "               if (adir.y > adir.z) // Y\n"
1151 "               {\n"
1152 "                       ma = adir.y;\n"
1153 "                       tc = dir.xz;\n"
1154 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1155 "               }\n"
1156 "               else // Z\n"
1157 "               {\n"
1158 "                       ma = adir.z;\n"
1159 "                       tc = dir.xy;\n"
1160 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1161 "               }\n"
1162 "       }\n"
1163 "\n"
1164 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1165 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1166 "       stc.z += ShadowMap_Parameters.z;\n"
1167 "       return stc;\n"
1168 "# else\n"
1169 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1170 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1171 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1172 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1173 "       stc.z += ShadowMap_Parameters.z;\n"
1174 "       return stc;\n"
1175 "# endif\n"
1176 "}\n"
1177 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1178 "\n"
1179 "#ifdef USESHADOWMAPCUBE\n"
1180 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1181 "{\n"
1182 "    vec3 adir = abs(dir);\n"
1183 "    return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1184 "}\n"
1185 "#endif\n"
1186 "\n"
1187 "# ifdef USESHADOWMAPRECT\n"
1188 "float ShadowMapCompare(vec3 dir)\n"
1189 "{\n"
1190 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1191 "       float f;\n"
1192 "#  ifdef USESHADOWSAMPLER\n"
1193 "\n"
1194 "#    ifdef USESHADOWMAPPCF\n"
1195 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1196 "    f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1197 "#    else\n"
1198 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1199 "#    endif\n"
1200 "\n"
1201 "#  else\n"
1202 "\n"
1203 "#    ifdef USESHADOWMAPPCF\n"
1204 "#      if USESHADOWMAPPCF > 1\n"
1205 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1206 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1207 "    vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1208 "    vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1209 "    vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1210 "    vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1211 "    vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1212 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1213 "#      else\n"
1214 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1215 "    vec2 offset = fract(shadowmaptc.xy);\n"
1216 "    vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1217 "    vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1218 "    vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1219 "    vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1220 "    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1221 "#      endif\n"
1222 "#    else\n"
1223 "    f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1224 "#    endif\n"
1225 "\n"
1226 "#  endif\n"
1227 "       return f;\n"
1228 "}\n"
1229 "# endif\n"
1230 "\n"
1231 "# ifdef USESHADOWMAP2D\n"
1232 "float ShadowMapCompare(vec3 dir)\n"
1233 "{\n"
1234 "    vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1235 "    float f;\n"
1236 "\n"
1237 "#  ifdef USESHADOWSAMPLER\n"
1238 "#    ifdef USESHADOWMAPPCF\n"
1239 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1240 "    vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1241 "    f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1242 "#    else\n"
1243 "    f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1244 "#    endif\n"
1245 "#  else\n"
1246 "#    ifdef USESHADOWMAPPCF\n"
1247 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1248 "#      ifdef GL_ARB_texture_gather\n"
1249 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1250 "#      else\n"
1251 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1252 "#      endif\n"
1253 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1254 "    center *= ShadowMap_TextureScale;\n"
1255 "    vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1256 "    vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1257 "    vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1258 "    vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1259 "    vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1260 "                mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1261 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1262 "#     else\n"
1263 "#      ifdef GL_EXT_gpu_shader4\n"
1264 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1265 "#      else\n"
1266 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1267 "#      endif\n"
1268 "#      if USESHADOWMAPPCF > 1\n"
1269 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1270 "    center *= ShadowMap_TextureScale;\n"
1271 "    vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1272 "    vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1273 "    vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1274 "    vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1275 "    vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1276 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1277 "#      else\n"
1278 "    vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1279 "    vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1280 "    vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1281 "    vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1282 "    vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1283 "    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1284 "#      endif\n"
1285 "#     endif\n"
1286 "#    else\n"
1287 "    f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1288 "#    endif\n"
1289 "#  endif\n"
1290 "    return f;\n"
1291 "}\n"
1292 "# endif\n"
1293 "\n"
1294 "# ifdef USESHADOWMAPCUBE\n"
1295 "float ShadowMapCompare(vec3 dir)\n"
1296 "{\n"
1297 "    // apply depth texture cubemap as light filter\n"
1298 "    vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1299 "    float f;\n"
1300 "#  ifdef USESHADOWSAMPLER\n"
1301 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1302 "#  else\n"
1303 "    f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1304 "#  endif\n"
1305 "    return f;\n"
1306 "}\n"
1307 "# endif\n"
1308 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1309 "\n"
1310 "#ifdef MODE_DEFERREDGEOMETRY\n"
1311 "void main(void)\n"
1312 "{\n"
1313 "#ifdef USEOFFSETMAPPING\n"
1314 "       // apply offsetmapping\n"
1315 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1316 "#define TexCoord TexCoordOffset\n"
1317 "#endif\n"
1318 "\n"
1319 "#ifdef USEALPHAKILL\n"
1320 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1321 "               discard;\n"
1322 "#endif\n"
1323 "\n"
1324 "#ifdef USEVERTEXTEXTUREBLEND\n"
1325 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1326 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1327 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1328 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1329 "#endif\n"
1330 "\n"
1331 "#ifdef USEVERTEXTEXTUREBLEND\n"
1332 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1333 "#else\n"
1334 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1335 "#endif\n"
1336 "\n"
1337 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1338 "}\n"
1339 "#else // !MODE_DEFERREDGEOMETRY\n"
1340 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1341 "uniform mat4 ViewToLight;\n"
1342 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1343 "uniform vec2 ScreenToDepth;\n"
1344 "uniform myhalf3 DeferredColor_Ambient;\n"
1345 "uniform myhalf3 DeferredColor_Diffuse;\n"
1346 "#ifdef USESPECULAR\n"
1347 "uniform myhalf3 DeferredColor_Specular;\n"
1348 "uniform myhalf SpecularPower;\n"
1349 "#endif\n"
1350 "void main(void)\n"
1351 "{\n"
1352 "       // calculate viewspace pixel position\n"
1353 "       vec3 position;\n"
1354 "       position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1355 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1356 "       // decode viewspace pixel normal\n"
1357 "       myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1358 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1359 "       // surfacenormal = pixel normal in viewspace\n"
1360 "       // LightVector = pixel to light in viewspace\n"
1361 "       // CubeVector = position in lightspace\n"
1362 "       // eyevector = pixel to view in viewspace\n"
1363 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1364 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1365 "#ifdef USEDIFFUSE\n"
1366 "       // calculate diffuse shading\n"
1367 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1368 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1369 "#endif\n"
1370 "#ifdef USESPECULAR\n"
1371 "       // calculate directional shading\n"
1372 "       vec3 eyevector = position * -1.0;\n"
1373 "#  ifdef USEEXACTSPECULARMATH\n"
1374 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1375 "#  else\n"
1376 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1377 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1378 "#  endif\n"
1379 "#endif\n"
1380 "\n"
1381 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1382 "       fade *= ShadowMapCompare(CubeVector);\n"
1383 "#endif\n"
1384 "\n"
1385 "#ifdef USEDIFFUSE\n"
1386 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1387 "#else\n"
1388 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1389 "#endif\n"
1390 "#ifdef USESPECULAR\n"
1391 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1392 "#else\n"
1393 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1394 "#endif\n"
1395 "\n"
1396 "# ifdef USECUBEFILTER\n"
1397 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1398 "       gl_FragData[0] *= cubecolor;\n"
1399 "       gl_FragData[1] *= cubecolor;\n"
1400 "# endif\n"
1401 "}\n"
1402 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1403 "#ifdef USEDEFERREDLIGHTMAP\n"
1404 "uniform myhalf3 DeferredMod_Diffuse;\n"
1405 "uniform myhalf3 DeferredMod_Specular;\n"
1406 "#endif\n"
1407 "uniform myhalf3 Color_Ambient;\n"
1408 "uniform myhalf3 Color_Diffuse;\n"
1409 "uniform myhalf3 Color_Specular;\n"
1410 "uniform myhalf SpecularPower;\n"
1411 "#ifdef USEGLOW\n"
1412 "uniform myhalf3 Color_Glow;\n"
1413 "#endif\n"
1414 "uniform myhalf Alpha;\n"
1415 "#ifdef USEREFLECTION\n"
1416 "uniform vec4 DistortScaleRefractReflect;\n"
1417 "uniform vec4 ScreenScaleRefractReflect;\n"
1418 "uniform vec4 ScreenCenterRefractReflect;\n"
1419 "uniform myhalf4 ReflectColor;\n"
1420 "#endif\n"
1421 "#ifdef MODE_LIGHTDIRECTION\n"
1422 "uniform myhalf3 LightColor;\n"
1423 "#endif\n"
1424 "#ifdef MODE_LIGHTSOURCE\n"
1425 "uniform myhalf3 LightColor;\n"
1426 "#endif\n"
1427 "void main(void)\n"
1428 "{\n"
1429 "#ifdef USEOFFSETMAPPING\n"
1430 "       // apply offsetmapping\n"
1431 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1432 "#define TexCoord TexCoordOffset\n"
1433 "#endif\n"
1434 "\n"
1435 "       // combine the diffuse textures (base, pants, shirt)\n"
1436 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1437 "#ifdef USEALPHAKILL\n"
1438 "       if (color.a < 0.5)\n"
1439 "               discard;\n"
1440 "#endif\n"
1441 "       color.a *= Alpha;\n"
1442 "#ifdef USECOLORMAPPING\n"
1443 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1444 "#endif\n"
1445 "#ifdef USEVERTEXTEXTUREBLEND\n"
1446 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1447 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1448 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1449 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1450 "       color.a = 1.0;\n"
1451 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1452 "#endif\n"
1453 "\n"
1454 "       // get the surface normal\n"
1455 "#ifdef USEVERTEXTEXTUREBLEND\n"
1456 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1457 "#else\n"
1458 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1459 "#endif\n"
1460 "\n"
1461 "       // get the material colors\n"
1462 "       myhalf3 diffusetex = color.rgb;\n"
1463 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1464 "# ifdef USEVERTEXTEXTUREBLEND\n"
1465 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1466 "# else\n"
1467 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1468 "# endif\n"
1469 "#endif\n"
1470 "\n"
1471 "\n"
1472 "\n"
1473 "\n"
1474 "#ifdef MODE_LIGHTSOURCE\n"
1475 "       // light source\n"
1476 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1477 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1478 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1479 "#ifdef USESPECULAR\n"
1480 "#ifdef USEEXACTSPECULARMATH\n"
1481 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1482 "#else\n"
1483 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1484 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1485 "#endif\n"
1486 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1487 "#endif\n"
1488 "       color.rgb *= LightColor;\n"
1489 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1490 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1491 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1492 "#endif\n"
1493 "# ifdef USECUBEFILTER\n"
1494 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1495 "# endif\n"
1496 "#endif // MODE_LIGHTSOURCE\n"
1497 "\n"
1498 "\n"
1499 "\n"
1500 "\n"
1501 "#ifdef MODE_LIGHTDIRECTION\n"
1502 "#define SHADING\n"
1503 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1504 "#define lightcolor LightColor\n"
1505 "#endif // MODE_LIGHTDIRECTION\n"
1506 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1507 "#define SHADING\n"
1508 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1509 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1510 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1511 "       // convert modelspace light vector to tangentspace\n"
1512 "       myhalf3 lightnormal;\n"
1513 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1514 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1515 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1516 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1517 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1518 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1519 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1520 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1521 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1522 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1523 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1524 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1525 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1526 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1527 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1528 "#define SHADING\n"
1529 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1530 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1531 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1532 "#endif\n"
1533 "\n"
1534 "\n"
1535 "\n"
1536 "\n"
1537 "#ifdef MODE_LIGHTMAP\n"
1538 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1539 "#endif // MODE_LIGHTMAP\n"
1540 "#ifdef MODE_VERTEXCOLOR\n"
1541 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1542 "#endif // MODE_VERTEXCOLOR\n"
1543 "#ifdef MODE_FLATCOLOR\n"
1544 "       color.rgb = diffusetex * Color_Ambient;\n"
1545 "#endif // MODE_FLATCOLOR\n"
1546 "\n"
1547 "\n"
1548 "\n"
1549 "\n"
1550 "#ifdef SHADING\n"
1551 "# ifdef USEDIFFUSE\n"
1552 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1553 "#  ifdef USESPECULAR\n"
1554 "#   ifdef USEEXACTSPECULARMATH\n"
1555 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1556 "#   else\n"
1557 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1558 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1559 "#   endif\n"
1560 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1561 "#  else\n"
1562 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1563 "#  endif\n"
1564 "# else\n"
1565 "       color.rgb = diffusetex * Color_Ambient;\n"
1566 "# endif\n"
1567 "#endif\n"
1568 "\n"
1569 "#ifdef USEDEFERREDLIGHTMAP\n"
1570 "       color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1571 "       color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1572 "#endif\n"
1573 "\n"
1574 "#ifdef USEGLOW\n"
1575 "#ifdef USEVERTEXTEXTUREBLEND\n"
1576 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1577 "#else\n"
1578 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1579 "#endif\n"
1580 "#endif\n"
1581 "\n"
1582 "#ifdef USEFOG\n"
1583 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1584 "#endif\n"
1585 "\n"
1586 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1587 "#ifdef USEREFLECTION\n"
1588 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1589 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1590 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1591 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1592 "       // FIXME temporary hack to detect the case that the reflection\n"
1593 "       // gets blackened at edges due to leaving the area that contains actual\n"
1594 "       // content.\n"
1595 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1596 "       // 'appening.\n"
1597 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1598 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1599 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1600 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1601 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1602 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1603 "#endif\n"
1604 "\n"
1605 "       gl_FragColor = vec4(color);\n"
1606 "}\n"
1607 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1608 "#endif // !MODE_DEFERREDGEOMETRY\n"
1609 "\n"
1610 "#endif // FRAGMENT_SHADER\n"
1611 "\n"
1612 "#endif // !MODE_WATER\n"
1613 "#endif // !MODE_REFRACTION\n"
1614 "#endif // !MODE_BLOOMBLUR\n"
1615 "#endif // !MODE_GENERIC\n"
1616 "#endif // !MODE_POSTPROCESS\n"
1617 "#endif // !MODE_SHOWDEPTH\n"
1618 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1619 ;
1620
1621 const char *builtincgshaderstring = "";
1622
1623 typedef struct shaderpermutationinfo_s
1624 {
1625         const char *pretext;
1626         const char *name;
1627 }
1628 shaderpermutationinfo_t;
1629
1630 typedef struct shadermodeinfo_s
1631 {
1632         const char *vertexfilename;
1633         const char *geometryfilename;
1634         const char *fragmentfilename;
1635         const char *pretext;
1636         const char *name;
1637 }
1638 shadermodeinfo_t;
1639
1640 typedef enum shaderpermutation_e
1641 {
1642         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1643         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1644         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1645         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1646         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1647         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1648         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1649         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1650         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1651         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1652         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1653         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1654         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1655         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1656         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1657         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1658         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1659         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1660         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1661         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1662         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1663         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1664         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1665         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1666         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1667         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
1668         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
1669         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
1670 }
1671 shaderpermutation_t;
1672
1673 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1674 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1675 {
1676         {"#define USEDIFFUSE\n", " diffuse"},
1677         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1678         {"#define USEVIEWTINT\n", " viewtint"},
1679         {"#define USECOLORMAPPING\n", " colormapping"},
1680         {"#define USESATURATION\n", " saturation"},
1681         {"#define USEFOGINSIDE\n", " foginside"},
1682         {"#define USEFOGOUTSIDE\n", " fogoutside"},
1683         {"#define USEGAMMARAMPS\n", " gammaramps"},
1684         {"#define USECUBEFILTER\n", " cubefilter"},
1685         {"#define USEGLOW\n", " glow"},
1686         {"#define USEBLOOM\n", " bloom"},
1687         {"#define USESPECULAR\n", " specular"},
1688         {"#define USEPOSTPROCESSING\n", " postprocessing"},
1689         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1690         {"#define USEREFLECTION\n", " reflection"},
1691         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1692         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1693         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1694         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1695         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1696         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1697         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1698         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1699         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1700         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1701         {"#define USEALPHAKILL\n", " alphakill"},
1702 };
1703
1704 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1705 typedef enum shadermode_e
1706 {
1707         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1708         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1709         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1710         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1711         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1712         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1713         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1714         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1715         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1716         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1717         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1718         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1719         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1720         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1721         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1722         SHADERMODE_COUNT
1723 }
1724 shadermode_t;
1725
1726 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1727 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
1728 {
1729         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1730         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1731         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1732         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1733         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1734         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1735         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1736         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1737         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1738         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1739         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1740         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1741         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1742         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1743         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1744 };
1745
1746 #ifdef SUPPORTCG
1747 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
1748 {
1749         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
1750         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
1751         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1752         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
1753         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1754         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
1755         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1756         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1757         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1758         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1759         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
1760         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
1761         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
1762         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1763         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1764 };
1765 #endif
1766
1767 struct r_glsl_permutation_s;
1768 typedef struct r_glsl_permutation_s
1769 {
1770         /// hash lookup data
1771         struct r_glsl_permutation_s *hashnext;
1772         unsigned int mode;
1773         unsigned int permutation;
1774
1775         /// indicates if we have tried compiling this permutation already
1776         qboolean compiled;
1777         /// 0 if compilation failed
1778         int program;
1779         /// locations of detected uniforms in program object, or -1 if not found
1780         int loc_Texture_First;
1781         int loc_Texture_Second;
1782         int loc_Texture_GammaRamps;
1783         int loc_Texture_Normal;
1784         int loc_Texture_Color;
1785         int loc_Texture_Gloss;
1786         int loc_Texture_Glow;
1787         int loc_Texture_SecondaryNormal;
1788         int loc_Texture_SecondaryColor;
1789         int loc_Texture_SecondaryGloss;
1790         int loc_Texture_SecondaryGlow;
1791         int loc_Texture_Pants;
1792         int loc_Texture_Shirt;
1793         int loc_Texture_FogMask;
1794         int loc_Texture_Lightmap;
1795         int loc_Texture_Deluxemap;
1796         int loc_Texture_Attenuation;
1797         int loc_Texture_Cube;
1798         int loc_Texture_Refraction;
1799         int loc_Texture_Reflection;
1800         int loc_Texture_ShadowMapRect;
1801         int loc_Texture_ShadowMapCube;
1802         int loc_Texture_ShadowMap2D;
1803         int loc_Texture_CubeProjection;
1804         int loc_Texture_ScreenDepth;
1805         int loc_Texture_ScreenNormalMap;
1806         int loc_Texture_ScreenDiffuse;
1807         int loc_Texture_ScreenSpecular;
1808         int loc_Alpha;
1809         int loc_BloomBlur_Parameters;
1810         int loc_ClientTime;
1811         int loc_Color_Ambient;
1812         int loc_Color_Diffuse;
1813         int loc_Color_Specular;
1814         int loc_Color_Glow;
1815         int loc_Color_Pants;
1816         int loc_Color_Shirt;
1817         int loc_DeferredColor_Ambient;
1818         int loc_DeferredColor_Diffuse;
1819         int loc_DeferredColor_Specular;
1820         int loc_DeferredMod_Diffuse;
1821         int loc_DeferredMod_Specular;
1822         int loc_DistortScaleRefractReflect;
1823         int loc_EyePosition;
1824         int loc_FogColor;
1825         int loc_FogHeightFade;
1826         int loc_FogPlane;
1827         int loc_FogPlaneViewDist;
1828         int loc_FogRangeRecip;
1829         int loc_LightColor;
1830         int loc_LightDir;
1831         int loc_LightPosition;
1832         int loc_OffsetMapping_Scale;
1833         int loc_PixelSize;
1834         int loc_ReflectColor;
1835         int loc_ReflectFactor;
1836         int loc_ReflectOffset;
1837         int loc_RefractColor;
1838         int loc_Saturation;
1839         int loc_ScreenCenterRefractReflect;
1840         int loc_ScreenScaleRefractReflect;
1841         int loc_ScreenToDepth;
1842         int loc_ShadowMap_Parameters;
1843         int loc_ShadowMap_TextureScale;
1844         int loc_SpecularPower;
1845         int loc_UserVec1;
1846         int loc_UserVec2;
1847         int loc_UserVec3;
1848         int loc_UserVec4;
1849         int loc_ViewTintColor;
1850         int loc_ViewToLight;
1851         int loc_ModelToLight;
1852         int loc_TexMatrix;
1853         int loc_BackgroundTexMatrix;
1854         int loc_ModelViewProjectionMatrix;
1855         int loc_ModelViewMatrix;
1856 }
1857 r_glsl_permutation_t;
1858
1859 #define SHADERPERMUTATION_HASHSIZE 256
1860
1861 /// information about each possible shader permutation
1862 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1863 /// currently selected permutation
1864 r_glsl_permutation_t *r_glsl_permutation;
1865 /// storage for permutations linked in the hash table
1866 memexpandablearray_t r_glsl_permutationarray;
1867
1868 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1869 {
1870         //unsigned int hashdepth = 0;
1871         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1872         r_glsl_permutation_t *p;
1873         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1874         {
1875                 if (p->mode == mode && p->permutation == permutation)
1876                 {
1877                         //if (hashdepth > 10)
1878                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1879                         return p;
1880                 }
1881                 //hashdepth++;
1882         }
1883         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1884         p->mode = mode;
1885         p->permutation = permutation;
1886         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1887         r_glsl_permutationhash[mode][hashindex] = p;
1888         //if (hashdepth > 10)
1889         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1890         return p;
1891 }
1892
1893 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1894 {
1895         char *shaderstring;
1896         if (!filename || !filename[0])
1897                 return NULL;
1898         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1899         if (shaderstring)
1900         {
1901                 if (printfromdisknotice)
1902                         Con_DPrintf("from disk %s... ", filename);
1903                 return shaderstring;
1904         }
1905         else if (!strcmp(filename, "glsl/default.glsl"))
1906         {
1907                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1908                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1909         }
1910         return shaderstring;
1911 }
1912
1913 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1914 {
1915         int i;
1916         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1917         int vertstrings_count = 0;
1918         int geomstrings_count = 0;
1919         int fragstrings_count = 0;
1920         char *vertexstring, *geometrystring, *fragmentstring;
1921         const char *vertstrings_list[32+3];
1922         const char *geomstrings_list[32+3];
1923         const char *fragstrings_list[32+3];
1924         char permutationname[256];
1925
1926         if (p->compiled)
1927                 return;
1928         p->compiled = true;
1929         p->program = 0;
1930
1931         permutationname[0] = 0;
1932         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1933         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1934         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1935
1936         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1937
1938         // the first pretext is which type of shader to compile as
1939         // (later these will all be bound together as a program object)
1940         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1941         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1942         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1943
1944         // the second pretext is the mode (for example a light source)
1945         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1946         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1947         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1948         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1949
1950         // now add all the permutation pretexts
1951         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1952         {
1953                 if (permutation & (1<<i))
1954                 {
1955                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1956                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1957                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1958                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1959                 }
1960                 else
1961                 {
1962                         // keep line numbers correct
1963                         vertstrings_list[vertstrings_count++] = "\n";
1964                         geomstrings_list[geomstrings_count++] = "\n";
1965                         fragstrings_list[fragstrings_count++] = "\n";
1966                 }
1967         }
1968
1969         // now append the shader text itself
1970         vertstrings_list[vertstrings_count++] = vertexstring;
1971         geomstrings_list[geomstrings_count++] = geometrystring;
1972         fragstrings_list[fragstrings_count++] = fragmentstring;
1973
1974         // if any sources were NULL, clear the respective list
1975         if (!vertexstring)
1976                 vertstrings_count = 0;
1977         if (!geometrystring)
1978                 geomstrings_count = 0;
1979         if (!fragmentstring)
1980                 fragstrings_count = 0;
1981
1982         // compile the shader program
1983         if (vertstrings_count + geomstrings_count + fragstrings_count)
1984                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1985         if (p->program)
1986         {
1987                 CHECKGLERROR
1988                 qglUseProgramObjectARB(p->program);CHECKGLERROR
1989                 // look up all the uniform variable names we care about, so we don't
1990                 // have to look them up every time we set them
1991
1992                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
1993                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
1994                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1995                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
1996                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
1997                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1998                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
1999                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
2000                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
2001                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
2002                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
2003                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
2004                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
2005                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
2006                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
2007                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
2008                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
2009                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
2010                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
2011                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
2012                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
2013                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
2014                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
2015                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
2016                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
2017                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
2018                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
2019                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
2020                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
2021                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
2022                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
2023                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
2024                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
2025                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
2026                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
2027                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
2028                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
2029                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
2030                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
2031                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
2032                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
2033                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
2034                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
2035                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
2036                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
2037                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
2038                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
2039                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
2040                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
2041                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
2042                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
2043                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
2044                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
2045                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
2046                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
2047                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
2048                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
2049                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
2050                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
2051                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
2052                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2053                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2054                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2055                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2056                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
2057                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
2058                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
2059                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
2060                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
2061                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
2062                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
2063                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
2064                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
2065                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
2066                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
2067                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
2068                 // initialize the samplers to refer to the texture units we use
2069                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
2070                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
2071                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
2072                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
2073                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
2074                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
2075                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
2076                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2077                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2078                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2079                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
2080                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
2081                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
2082                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
2083                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
2084                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
2085                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
2086                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
2087                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
2088                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
2089                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
2090                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
2091                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
2092                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2093                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
2094                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2095                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
2096                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2097                 CHECKGLERROR
2098                 if (developer.integer)
2099                         Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2100         }
2101         else
2102                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
2103
2104         // free the strings
2105         if (vertexstring)
2106                 Mem_Free(vertexstring);
2107         if (geometrystring)
2108                 Mem_Free(geometrystring);
2109         if (fragmentstring)
2110                 Mem_Free(fragmentstring);
2111 }
2112
2113 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
2114 {
2115         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2116         if (r_glsl_permutation != perm)
2117         {
2118                 r_glsl_permutation = perm;
2119                 if (!r_glsl_permutation->program)
2120                 {
2121                         if (!r_glsl_permutation->compiled)
2122                                 R_GLSL_CompilePermutation(perm, mode, permutation);
2123                         if (!r_glsl_permutation->program)
2124                         {
2125                                 // remove features until we find a valid permutation
2126                                 int i;
2127                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2128                                 {
2129                                         // reduce i more quickly whenever it would not remove any bits
2130                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2131                                         if (!(permutation & j))
2132                                                 continue;
2133                                         permutation -= j;
2134                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2135                                         if (!r_glsl_permutation->compiled)
2136                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
2137                                         if (r_glsl_permutation->program)
2138                                                 break;
2139                                 }
2140                                 if (i >= SHADERPERMUTATION_COUNT)
2141                                 {
2142                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2143                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2144                                         qglUseProgramObjectARB(0);CHECKGLERROR
2145                                         return; // no bit left to clear, entire mode is broken
2146                                 }
2147                         }
2148                 }
2149                 CHECKGLERROR
2150                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2151         }
2152         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
2153 }
2154
2155 #ifdef SUPPORTCG
2156 #include <Cg/cgGL.h>
2157 struct r_cg_permutation_s;
2158 typedef struct r_cg_permutation_s
2159 {
2160         /// hash lookup data
2161         struct r_cg_permutation_s *hashnext;
2162         unsigned int mode;
2163         unsigned int permutation;
2164
2165         /// indicates if we have tried compiling this permutation already
2166         qboolean compiled;
2167         /// 0 if compilation failed
2168         CGprogram vprogram;
2169         CGprogram fprogram;
2170         /// locations of detected parameters in programs, or NULL if not found
2171         CGparameter vp_EyePosition;
2172         CGparameter vp_FogPlane;
2173         CGparameter vp_LightDir;
2174         CGparameter vp_LightPosition;
2175         CGparameter vp_ModelToLight;
2176         CGparameter vp_TexMatrix;
2177         CGparameter vp_BackgroundTexMatrix;
2178         CGparameter vp_ModelViewProjectionMatrix;
2179         CGparameter vp_ModelViewMatrix;
2180
2181         CGparameter fp_Texture_First;
2182         CGparameter fp_Texture_Second;
2183         CGparameter fp_Texture_GammaRamps;
2184         CGparameter fp_Texture_Normal;
2185         CGparameter fp_Texture_Color;
2186         CGparameter fp_Texture_Gloss;
2187         CGparameter fp_Texture_Glow;
2188         CGparameter fp_Texture_SecondaryNormal;
2189         CGparameter fp_Texture_SecondaryColor;
2190         CGparameter fp_Texture_SecondaryGloss;
2191         CGparameter fp_Texture_SecondaryGlow;
2192         CGparameter fp_Texture_Pants;
2193         CGparameter fp_Texture_Shirt;
2194         CGparameter fp_Texture_FogMask;
2195         CGparameter fp_Texture_Lightmap;
2196         CGparameter fp_Texture_Deluxemap;
2197         CGparameter fp_Texture_Attenuation;
2198         CGparameter fp_Texture_Cube;
2199         CGparameter fp_Texture_Refraction;
2200         CGparameter fp_Texture_Reflection;
2201         CGparameter fp_Texture_ShadowMapRect;
2202         CGparameter fp_Texture_ShadowMapCube;
2203         CGparameter fp_Texture_ShadowMap2D;
2204         CGparameter fp_Texture_CubeProjection;
2205         CGparameter fp_Texture_ScreenDepth;
2206         CGparameter fp_Texture_ScreenNormalMap;
2207         CGparameter fp_Texture_ScreenDiffuse;
2208         CGparameter fp_Texture_ScreenSpecular;
2209         CGparameter fp_Alpha;
2210         CGparameter fp_BloomBlur_Parameters;
2211         CGparameter fp_ClientTime;
2212         CGparameter fp_Color_Ambient;
2213         CGparameter fp_Color_Diffuse;
2214         CGparameter fp_Color_Specular;
2215         CGparameter fp_Color_Glow;
2216         CGparameter fp_Color_Pants;
2217         CGparameter fp_Color_Shirt;
2218         CGparameter fp_DeferredColor_Ambient;
2219         CGparameter fp_DeferredColor_Diffuse;
2220         CGparameter fp_DeferredColor_Specular;
2221         CGparameter fp_DeferredMod_Diffuse;
2222         CGparameter fp_DeferredMod_Specular;
2223         CGparameter fp_DistortScaleRefractReflect;
2224         CGparameter fp_EyePosition;
2225         CGparameter fp_FogColor;
2226         CGparameter fp_FogHeightFade;
2227         CGparameter fp_FogPlane;
2228         CGparameter fp_FogPlaneViewDist;
2229         CGparameter fp_FogRangeRecip;
2230         CGparameter fp_LightColor;
2231         CGparameter fp_LightDir;
2232         CGparameter fp_LightPosition;
2233         CGparameter fp_OffsetMapping_Scale;
2234         CGparameter fp_PixelSize;
2235         CGparameter fp_ReflectColor;
2236         CGparameter fp_ReflectFactor;
2237         CGparameter fp_ReflectOffset;
2238         CGparameter fp_RefractColor;
2239         CGparameter fp_Saturation;
2240         CGparameter fp_ScreenCenterRefractReflect;
2241         CGparameter fp_ScreenScaleRefractReflect;
2242         CGparameter fp_ScreenToDepth;
2243         CGparameter fp_ShadowMap_Parameters;
2244         CGparameter fp_ShadowMap_TextureScale;
2245         CGparameter fp_SpecularPower;
2246         CGparameter fp_UserVec1;
2247         CGparameter fp_UserVec2;
2248         CGparameter fp_UserVec3;
2249         CGparameter fp_UserVec4;
2250         CGparameter fp_ViewTintColor;
2251         CGparameter fp_ViewToLight;
2252 }
2253 r_cg_permutation_t;
2254
2255 /// information about each possible shader permutation
2256 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
2257 /// currently selected permutation
2258 r_cg_permutation_t *r_cg_permutation;
2259 /// storage for permutations linked in the hash table
2260 memexpandablearray_t r_cg_permutationarray;
2261
2262 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
2263 {
2264         //unsigned int hashdepth = 0;
2265         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
2266         r_cg_permutation_t *p;
2267         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
2268         {
2269                 if (p->mode == mode && p->permutation == permutation)
2270                 {
2271                         //if (hashdepth > 10)
2272                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
2273                         return p;
2274                 }
2275                 //hashdepth++;
2276         }
2277         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
2278         p->mode = mode;
2279         p->permutation = permutation;
2280         p->hashnext = r_cg_permutationhash[mode][hashindex];
2281         r_cg_permutationhash[mode][hashindex] = p;
2282         //if (hashdepth > 10)
2283         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
2284         return p;
2285 }
2286
2287 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
2288 {
2289         char *shaderstring;
2290         if (!filename || !filename[0])
2291                 return NULL;
2292         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
2293         if (shaderstring)
2294         {
2295                 if (printfromdisknotice)
2296                         Con_DPrintf("from disk %s... ", filename);
2297                 return shaderstring;
2298         }
2299         else if (!strcmp(filename, "cg/default.cg"))
2300         {
2301                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
2302                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
2303         }
2304         return shaderstring;
2305 }
2306
2307 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
2308 {
2309         int i;
2310         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
2311         int vertstrings_count = 0, vertstring_length = 0;
2312         int geomstrings_count = 0, geomstring_length = 0;
2313         int fragstrings_count = 0, fragstring_length = 0;
2314         char *t;
2315         char *vertexstring, *geometrystring, *fragmentstring;
2316         char *vertstring, *geomstring, *fragstring;
2317         const char *vertstrings_list[32+3];
2318         const char *geomstrings_list[32+3];
2319         const char *fragstrings_list[32+3];
2320         char permutationname[256];
2321
2322         if (p->compiled)
2323                 return;
2324         p->compiled = true;
2325         p->vprogram = NULL;
2326         p->fprogram = NULL;
2327
2328         permutationname[0] = 0;
2329         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
2330         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
2331         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
2332
2333         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
2334
2335         // the first pretext is which type of shader to compile as
2336         // (later these will all be bound together as a program object)
2337         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
2338         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
2339         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
2340
2341         // the second pretext is the mode (for example a light source)
2342         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
2343         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
2344         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
2345         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
2346
2347         // now add all the permutation pretexts
2348         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2349         {
2350                 if (permutation & (1<<i))
2351                 {
2352                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
2353                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
2354                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
2355                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
2356                 }
2357                 else
2358                 {
2359                         // keep line numbers correct
2360                         vertstrings_list[vertstrings_count++] = "\n";
2361                         geomstrings_list[geomstrings_count++] = "\n";
2362                         fragstrings_list[fragstrings_count++] = "\n";
2363                 }
2364         }
2365
2366         // now append the shader text itself
2367         vertstrings_list[vertstrings_count++] = vertexstring;
2368         geomstrings_list[geomstrings_count++] = geometrystring;
2369         fragstrings_list[fragstrings_count++] = fragmentstring;
2370
2371         // if any sources were NULL, clear the respective list
2372         if (!vertexstring)
2373                 vertstrings_count = 0;
2374         if (!geometrystring)
2375                 geomstrings_count = 0;
2376         if (!fragmentstring)
2377                 fragstrings_count = 0;
2378
2379         vertstring_length = 0;
2380         for (i = 0;i < vertstrings_count;i++)
2381                 vertstring_length += strlen(vertstrings_list[i]);
2382         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
2383         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
2384                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
2385
2386         geomstring_length = 0;
2387         for (i = 0;i < geomstrings_count;i++)
2388                 geomstring_length += strlen(geomstrings_list[i]);
2389         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
2390         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
2391                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
2392
2393         fragstring_length = 0;
2394         for (i = 0;i < fragstrings_count;i++)
2395                 fragstring_length += strlen(fragstrings_list[i]);
2396         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
2397         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
2398                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
2399
2400         // compile the shader program
2401         if (vertstring[0] || geomstring[0] || fragstring[0])
2402         {
2403                 if (vertstring[0])
2404                         p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL);
2405                 if (fragstring[0])
2406                         p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL);
2407         }
2408
2409         if (p->vprogram)
2410         {
2411                 cgGLBindProgram(p->vprogram);
2412                 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2413         }
2414         else
2415                 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2416         if (p->fprogram)
2417         {
2418                 cgGLBindProgram(p->fprogram);
2419                 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2420         }
2421         else
2422                 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2423
2424         if (p->vprogram || p->fprogram)
2425         {
2426                 // look up all the uniform variable names we care about, so we don't
2427                 // have to look them up every time we set them
2428                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
2429                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
2430                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
2431                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
2432                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
2433                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
2434                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
2435                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
2436                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
2437
2438                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
2439                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
2440                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
2441                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
2442                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
2443                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
2444                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
2445                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
2446                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
2447                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
2448                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
2449                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
2450                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
2451                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
2452                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
2453                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
2454                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
2455                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
2456                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
2457                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
2458                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
2459                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
2460                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
2461                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
2462                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
2463                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
2464                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
2465                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
2466                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
2467                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
2468                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
2469                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
2470                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
2471                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
2472                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
2473                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
2474                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
2475                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
2476                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
2477                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
2478                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
2479                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
2480                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
2481                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
2482                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
2483                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
2484                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
2485                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
2486                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
2487                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
2488                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
2489                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
2490                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
2491                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
2492                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
2493                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
2494                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
2495                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
2496                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
2497                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
2498                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
2499                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
2500                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
2501                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
2502                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
2503                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
2504                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
2505                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
2506                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
2507                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
2508                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
2509                 CHECKGLERROR
2510                 if (developer.integer)
2511                         Con_Printf("^5CG shader %s compiled.\n", permutationname);
2512         }
2513         else
2514                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
2515
2516         // free the strings
2517         if (vertstring)
2518                 Mem_Free(vertstring);
2519         if (geomstring)
2520                 Mem_Free(geomstring);
2521         if (fragstring)
2522                 Mem_Free(fragstring);
2523         if (vertexstring)
2524                 Mem_Free(vertexstring);
2525         if (geometrystring)
2526                 Mem_Free(geometrystring);
2527         if (fragmentstring)
2528                 Mem_Free(fragmentstring);
2529 }
2530
2531 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
2532 {
2533         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
2534         if (r_cg_permutation != perm)
2535         {
2536                 r_cg_permutation = perm;
2537                 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));
2538                 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2539                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
2540                 {
2541                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2542                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2543                         if (!r_cg_permutation->compiled)
2544                                 R_CG_CompilePermutation(perm, mode, permutation);
2545                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
2546                         {
2547                                 // remove features until we find a valid permutation
2548                                 int i;
2549                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2550                                 {
2551                                         // reduce i more quickly whenever it would not remove any bits
2552                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2553                                         if (!(permutation & j))
2554                                                 continue;
2555                                         permutation -= j;
2556                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
2557                                         if (!r_cg_permutation->compiled)
2558                                                 R_CG_CompilePermutation(perm, mode, permutation);
2559                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
2560                                                 break;
2561                                 }
2562                                 if (i >= SHADERPERMUTATION_COUNT)
2563                                 {
2564                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2565                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
2566                                         return; // no bit left to clear, entire mode is broken
2567                                 }
2568                         }
2569                 }
2570                 CHECKGLERROR
2571                 if (r_cg_permutation->vprogram)
2572                 {
2573                         cgGLBindProgram(r_cg_permutation->vprogram);
2574                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2575                 }
2576                 else
2577                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2578                 if (r_cg_permutation->fprogram)
2579                 {
2580                         cgGLBindProgram(r_cg_permutation->fprogram);
2581                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2582                 }
2583                 else
2584                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2585         }
2586         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);
2587 }
2588 #endif
2589
2590 void R_GLSL_Restart_f(void)
2591 {
2592         unsigned int i, limit;
2593         r_glsl_permutation_t *p;
2594         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2595         for (i = 0;i < limit;i++)
2596         {
2597                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2598                 {
2599                         GL_Backend_FreeProgram(p->program);
2600                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2601                 }
2602         }
2603         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2604 #ifdef SUPPORTCG
2605         if (vid.cgcontext)
2606         {
2607                 r_cg_permutation_t *p;
2608                 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
2609                 for (i = 0;i < limit;i++)
2610                 {
2611                         if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
2612                         {
2613                                 if (p->vprogram)
2614                                         cgDestroyProgram(p->vprogram);
2615                                 if (p->fprogram)
2616                                         cgDestroyProgram(p->fprogram);
2617                                 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
2618                         }
2619                 }
2620                 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
2621         }
2622 #endif
2623 }
2624
2625 void R_GLSL_DumpShader_f(void)
2626 {
2627         int i;
2628         qfile_t *file;
2629
2630         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2631         if (file)
2632         {
2633                 FS_Print(file, "/* The engine may define the following macros:\n");
2634                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2635                 for (i = 0;i < SHADERMODE_COUNT;i++)
2636                         FS_Print(file, glslshadermodeinfo[i].pretext);
2637                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2638                         FS_Print(file, shaderpermutationinfo[i].pretext);
2639                 FS_Print(file, "*/\n");
2640                 FS_Print(file, builtinshaderstring);
2641                 FS_Close(file);
2642                 Con_Printf("glsl/default.glsl written\n");
2643         }
2644         else
2645                 Con_Printf("failed to write to glsl/default.glsl\n");
2646
2647 #ifdef SUPPORTCG
2648         file = FS_OpenRealFile("cg/default.cg", "w", false);
2649         if (file)
2650         {
2651                 FS_Print(file, "/* The engine may define the following macros:\n");
2652                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2653                 for (i = 0;i < SHADERMODE_COUNT;i++)
2654                         FS_Print(file, cgshadermodeinfo[i].pretext);
2655                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2656                         FS_Print(file, shaderpermutationinfo[i].pretext);
2657                 FS_Print(file, "*/\n");
2658                 FS_Print(file, builtincgshaderstring);
2659                 FS_Close(file);
2660                 Con_Printf("cg/default.cg written\n");
2661         }
2662         else
2663                 Con_Printf("failed to write to cg/default.cg\n");
2664 #endif
2665 }
2666
2667 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
2668 {
2669         if (!second)
2670                 texturemode = GL_MODULATE;
2671         switch (vid.renderpath)
2672         {
2673         case RENDERPATH_GL20:
2674                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
2675                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(first ));
2676                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, R_GetTexture(second));
2677                 break;
2678         case RENDERPATH_CGGL:
2679                 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))));
2680                 if (r_cg_permutation->fp_Texture_First ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First , R_GetTexture(first ));
2681                 if (r_cg_permutation->fp_Texture_Second) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second, R_GetTexture(second));
2682                 break;
2683         case RENDERPATH_GL13:
2684                 R_Mesh_TexBind(0, R_GetTexture(first ));
2685                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2686                 R_Mesh_TexBind(1, R_GetTexture(second));
2687                 if (second)
2688                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2689                 break;
2690         case RENDERPATH_GL11:
2691                 R_Mesh_TexBind(0, R_GetTexture(first ));
2692                 break;
2693         }
2694 }
2695
2696 void R_SetupShader_DepthOrShadow(void)
2697 {
2698         switch (vid.renderpath)
2699         {
2700         case RENDERPATH_GL20:
2701                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
2702                 break;
2703         case RENDERPATH_CGGL:
2704                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
2705                 break;
2706         case RENDERPATH_GL13:
2707                 R_Mesh_TexBind(0, 0);
2708                 R_Mesh_TexBind(1, 0);
2709                 break;
2710         case RENDERPATH_GL11:
2711                 R_Mesh_TexBind(0, 0);
2712                 break;
2713         }
2714 }
2715
2716 void R_SetupShader_ShowDepth(void)
2717 {
2718         switch (vid.renderpath)
2719         {
2720         case RENDERPATH_GL20:
2721                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
2722                 break;
2723         case RENDERPATH_CGGL:
2724                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
2725                 break;
2726         case RENDERPATH_GL13:
2727                 break;
2728         case RENDERPATH_GL11:
2729                 break;
2730         }
2731 }
2732
2733 extern qboolean r_shadow_usingdeferredprepass;
2734 extern cvar_t r_shadow_deferred_8bitrange;
2735 extern rtexture_t *r_shadow_attenuationgradienttexture;
2736 extern rtexture_t *r_shadow_attenuation2dtexture;
2737 extern rtexture_t *r_shadow_attenuation3dtexture;
2738 extern qboolean r_shadow_usingshadowmaprect;
2739 extern qboolean r_shadow_usingshadowmapcube;
2740 extern qboolean r_shadow_usingshadowmap2d;
2741 extern float r_shadow_shadowmap_texturescale[2];
2742 extern float r_shadow_shadowmap_parameters[4];
2743 extern qboolean r_shadow_shadowmapvsdct;
2744 extern qboolean r_shadow_shadowmapsampler;
2745 extern int r_shadow_shadowmappcf;
2746 extern rtexture_t *r_shadow_shadowmaprectangletexture;
2747 extern rtexture_t *r_shadow_shadowmap2dtexture;
2748 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
2749 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2750 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2751 extern int r_shadow_prepass_width;
2752 extern int r_shadow_prepass_height;
2753 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2754 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2755 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2756 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2757 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2758 {
2759         // select a permutation of the lighting shader appropriate to this
2760         // combination of texture, entity, light source, and fogging, only use the
2761         // minimum features necessary to avoid wasting rendering time in the
2762         // fragment shader on features that are not being used
2763         unsigned int permutation = 0;
2764         unsigned int mode = 0;
2765         float m16f[16];
2766         // TODO: implement geometry-shader based shadow volumes someday
2767         if (r_glsl_offsetmapping.integer)
2768         {
2769                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2770                 if (r_glsl_offsetmapping_reliefmapping.integer)
2771                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2772         }
2773         if (rsurfacepass == RSURFPASS_BACKGROUND)
2774         {
2775                 // distorted background
2776                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2777                         mode = SHADERMODE_WATER;
2778                 else
2779                         mode = SHADERMODE_REFRACTION;
2780         }
2781         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2782         {
2783                 // normalmap (deferred prepass), may use alpha test on diffuse
2784                 mode = SHADERMODE_DEFERREDGEOMETRY;
2785                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2786                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2787                 if (r_glsl_offsetmapping.integer)
2788                 {
2789                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2790                         if (r_glsl_offsetmapping_reliefmapping.integer)
2791                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2792                 }
2793         }
2794         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2795         {
2796                 // light source
2797                 mode = SHADERMODE_LIGHTSOURCE;
2798                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2799                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2800                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2801                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2802                 if (diffusescale > 0)
2803                         permutation |= SHADERPERMUTATION_DIFFUSE;
2804                 if (specularscale > 0)
2805                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2806                 if (r_refdef.fogenabled)
2807                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2808                 if (rsurface.texture->colormapping)
2809                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2810                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2811                 {
2812                         if (r_shadow_usingshadowmaprect)
2813                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2814                         if (r_shadow_usingshadowmap2d)
2815                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2816                         if (r_shadow_usingshadowmapcube)
2817                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2818                         else if(r_shadow_shadowmapvsdct)
2819                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2820
2821                         if (r_shadow_shadowmapsampler)
2822                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2823                         if (r_shadow_shadowmappcf > 1)
2824                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2825                         else if (r_shadow_shadowmappcf)
2826                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2827                 }
2828         }
2829         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2830         {
2831                 // unshaded geometry (fullbright or ambient model lighting)
2832                 mode = SHADERMODE_FLATCOLOR;
2833                 ambientscale = diffusescale = specularscale = 0;
2834                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2835                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2836                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2837                         permutation |= SHADERPERMUTATION_GLOW;
2838                 if (r_refdef.fogenabled)
2839                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2840                 if (rsurface.texture->colormapping)
2841                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2842                 if (r_glsl_offsetmapping.integer)
2843                 {
2844                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2845                         if (r_glsl_offsetmapping_reliefmapping.integer)
2846                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2847                 }
2848                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2849                         permutation |= SHADERPERMUTATION_REFLECTION;
2850         }
2851         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2852         {
2853                 // directional model lighting
2854                 mode = SHADERMODE_LIGHTDIRECTION;
2855                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2856                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2857                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2858                         permutation |= SHADERPERMUTATION_GLOW;
2859                 permutation |= SHADERPERMUTATION_DIFFUSE;
2860                 if (specularscale > 0)
2861                         permutation |= SHADERPERMUTATION_SPECULAR;
2862                 if (r_refdef.fogenabled)
2863                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2864                 if (rsurface.texture->colormapping)
2865                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2866                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2867                         permutation |= SHADERPERMUTATION_REFLECTION;
2868                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2869                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2870         }
2871         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2872         {
2873                 // ambient model lighting
2874                 mode = SHADERMODE_LIGHTDIRECTION;
2875                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2876                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2877                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2878                         permutation |= SHADERPERMUTATION_GLOW;
2879                 if (r_refdef.fogenabled)
2880                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2881                 if (rsurface.texture->colormapping)
2882                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2883                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2884                         permutation |= SHADERPERMUTATION_REFLECTION;
2885                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2886                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2887         }
2888         else
2889         {
2890                 // lightmapped wall
2891                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2892                 {
2893                         // deluxemapping (light direction texture)
2894                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2895                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2896                         else
2897                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2898                         permutation |= SHADERPERMUTATION_DIFFUSE;
2899                         if (specularscale > 0)
2900                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2901                 }
2902                 else if (r_glsl_deluxemapping.integer >= 2)
2903                 {
2904                         // fake deluxemapping (uniform light direction in tangentspace)
2905                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2906                         permutation |= SHADERPERMUTATION_DIFFUSE;
2907                         if (specularscale > 0)
2908                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2909                 }
2910                 else if (rsurface.uselightmaptexture)
2911                 {
2912                         // ordinary lightmapping (q1bsp, q3bsp)
2913                         mode = SHADERMODE_LIGHTMAP;
2914                 }
2915                 else
2916                 {
2917                         // ordinary vertex coloring (q3bsp)
2918                         mode = SHADERMODE_VERTEXCOLOR;
2919                 }
2920                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2921                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2922                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2923                         permutation |= SHADERPERMUTATION_GLOW;
2924                 if (r_refdef.fogenabled)
2925                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2926                 if (rsurface.texture->colormapping)
2927                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2928                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2929                         permutation |= SHADERPERMUTATION_REFLECTION;
2930                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2931                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2932         }
2933         if(permutation & SHADERPERMUTATION_SPECULAR)
2934                 if(r_shadow_glossexact.integer)
2935                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2936         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
2937                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2938         switch(vid.renderpath)
2939         {
2940         case RENDERPATH_GL20:
2941                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2942                 if (mode == SHADERMODE_LIGHTSOURCE)
2943                 {
2944                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2945                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2946                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2947                         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);
2948                         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);
2949                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
2950         
2951                         // additive passes are only darkened by fog, not tinted
2952                         if (r_glsl_permutation->loc_FogColor >= 0)
2953                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2954                         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]);
2955                         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]);
2956                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2957                 }
2958                 else
2959                 {
2960                         if (mode == SHADERMODE_FLATCOLOR)
2961                         {
2962                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
2963                         }
2964                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2965                         {
2966                                 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]);
2967                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
2968                                 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);
2969                                 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);
2970                                 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);
2971                                 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]);
2972                                 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]);
2973                         }
2974                         else
2975                         {
2976                                 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]);
2977                                 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]);
2978                                 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);
2979                                 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);
2980                                 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);
2981                         }
2982                         // additive passes are only darkened by fog, not tinted
2983                         if (r_glsl_permutation->loc_FogColor >= 0)
2984                         {
2985                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2986                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2987                                 else
2988                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2989                         }
2990                         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);
2991                         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]);
2992                         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]);
2993                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2994                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2995                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2996                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2997                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2998                 }
2999                 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3000                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
3001                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
3002                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3003                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
3004                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3005                 if (r_glsl_permutation->loc_Color_Pants >= 0)
3006                 {
3007                         if (rsurface.texture->pantstexture)
3008                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3009                         else
3010                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
3011                 }
3012                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
3013                 {
3014                         if (rsurface.texture->shirttexture)
3015                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3016                         else
3017                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
3018                 }
3019                 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]);
3020                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
3021                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
3022                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
3023                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
3024                 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]);
3025
3026         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             ,          R_GetTexture(r_texture_white                                     ));
3027         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            ,          R_GetTexture(r_texture_white                                     ));
3028         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        ,          R_GetTexture(r_texture_gammaramps                                ));
3029                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            ,          R_GetTexture(rsurface.texture->nmaptexture                       ));
3030                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             ,          R_GetTexture(rsurface.texture->basetexture                       ));
3031                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             ,          R_GetTexture(rsurface.texture->glosstexture                      ));
3032                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              ,          R_GetTexture(rsurface.texture->glowtexture                       ));
3033                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  ,          R_GetTexture(rsurface.texture->backgroundnmaptexture             ));
3034                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   ,          R_GetTexture(rsurface.texture->backgroundbasetexture             ));
3035                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   ,          R_GetTexture(rsurface.texture->backgroundglosstexture            ));
3036                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    ,          R_GetTexture(rsurface.texture->backgroundglowtexture             ));
3037                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             ,          R_GetTexture(rsurface.texture->pantstexture                      ));
3038                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             ,          R_GetTexture(rsurface.texture->shirttexture                      ));
3039                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           ,          R_GetTexture(r_texture_fogattenuation                            ));
3040                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          ,          R_GetTexture(r_texture_white                                     ));
3041                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          ,          R_GetTexture(r_texture_blanknormalmap                            ));
3042                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       ,          R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3043                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        ,          R_GetTexture(r_texture_white                                     ));
3044                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        ,          R_GetTexture(r_texture_white                                     ));
3045                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH    , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3046                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3047                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE  , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture              ));
3048                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture             ));
3049                 if (rsurface.rtlight)
3050                 {
3051                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBindAll(GL20TU_CUBE           , 0, 0,    R_GetTexture(rsurface.rtlight->currentcubemap                    ), 0);
3052                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT  , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3053                         if (r_shadow_usingshadowmapcube)
3054                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE  , 0, 0,    R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
3055                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       ,          R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3056                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0,    R_GetTexture(r_shadow_shadowmapvsdcttexture                      ), 0);
3057                 }
3058                 CHECKGLERROR
3059                 break;
3060         case RENDERPATH_CGGL:
3061 #ifdef SUPPORTCG
3062                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3063                 if (mode == SHADERMODE_LIGHTSOURCE)
3064                 {
3065                         if (r_cg_permutation->vp_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}
3066                         if (r_cg_permutation->vp_LightPosition >= 0) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
3067                 }
3068                 else
3069                 {
3070                         if (mode == SHADERMODE_LIGHTDIRECTION)
3071                         {
3072                                 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]);
3073                         }
3074                 }
3075                 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);
3076                 if (r_cg_permutation->vp_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}
3077                 if (r_cg_permutation->vp_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}
3078                 if (r_cg_permutation->vp_EyePosition >= 0) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3079                 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]);
3080                 CHECKGLERROR
3081
3082                 if (mode == SHADERMODE_LIGHTSOURCE)
3083                 {
3084                         if (r_cg_permutation->fp_LightPosition >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
3085                         if (r_cg_permutation->fp_LightColor >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
3086                         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);
3087                         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);
3088                         if (r_cg_permutation->fp_Color_Specular >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);
3089
3090                         // additive passes are only darkened by fog, not tinted
3091                         if (r_cg_permutation->fp_FogColor >= 0)
3092                                 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
3093                         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]);
3094                         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]);
3095                         if (r_cg_permutation->fp_SpecularPower >= 0) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3096                 }
3097                 else
3098                 {
3099                         if (mode == SHADERMODE_FLATCOLOR)
3100                         {
3101                                 if (r_cg_permutation->fp_Color_Ambient >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
3102                         }
3103                         else if (mode == SHADERMODE_LIGHTDIRECTION)
3104                         {
3105                                 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]);
3106                                 if (r_cg_permutation->fp_Color_Diffuse >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
3107                                 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);
3108                                 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);
3109                                 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);
3110                                 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]);
3111                                 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]);
3112                         }
3113                         else
3114                         {
3115                                 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]);
3116                                 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]);
3117                                 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);
3118                                 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);
3119                                 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);
3120                         }
3121                         // additive passes are only darkened by fog, not tinted
3122                         if (r_cg_permutation->fp_FogColor >= 0)
3123                         {
3124                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
3125                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
3126                                 else
3127                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
3128                         }
3129                         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);
3130                         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]);
3131                         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]);
3132                         if (r_cg_permutation->fp_RefractColor >= 0) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);
3133                         if (r_cg_permutation->fp_ReflectColor >= 0) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);
3134                         if (r_cg_permutation->fp_ReflectFactor >= 0) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3135                         if (r_cg_permutation->fp_ReflectOffset >= 0) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);
3136                         if (r_cg_permutation->fp_SpecularPower >= 0) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3137                 }
3138                 if (r_cg_permutation->fp_Color_Glow >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3139                 if (r_cg_permutation->fp_Alpha >= 0) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);
3140                 if (r_cg_permutation->fp_EyePosition >= 0) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3141                 if (r_cg_permutation->fp_Color_Pants >= 0)
3142                 {
3143                         if (rsurface.texture->pantstexture)
3144                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3145                         else
3146                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
3147                 }
3148                 if (r_cg_permutation->fp_Color_Shirt >= 0)
3149                 {
3150                         if (rsurface.texture->shirttexture)
3151                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3152                         else
3153                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
3154                 }
3155                 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]);
3156                 if (r_cg_permutation->fp_FogPlaneViewDist >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);
3157                 if (r_cg_permutation->fp_FogRangeRecip >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);
3158                 if (r_cg_permutation->fp_FogHeightFade >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);
3159                 if (r_cg_permutation->fp_OffsetMapping_Scale >= 0) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
3160                 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]);
3161
3162         //      if (r_cg_permutation->fp_Texture_First          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First          , R_GetTexture(r_texture_white                                     ));
3163         //      if (r_cg_permutation->fp_Texture_Second         ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second         , R_GetTexture(r_texture_white                                     ));
3164         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_GammaRamps     , R_GetTexture(r_texture_gammaramps                                ));
3165                 if (r_cg_permutation->fp_Texture_Normal         ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Normal         , R_GetTexture(rsurface.texture->nmaptexture                       ));
3166                 if (r_cg_permutation->fp_Texture_Color          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Color          , R_GetTexture(rsurface.texture->basetexture                       ));
3167                 if (r_cg_permutation->fp_Texture_Gloss          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Gloss          , R_GetTexture(rsurface.texture->glosstexture                      ));
3168                 if (r_cg_permutation->fp_Texture_Glow           ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Glow           , R_GetTexture(rsurface.texture->glowtexture                       ));
3169                 if (r_cg_permutation->fp_Texture_SecondaryNormal) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryNormal, R_GetTexture(rsurface.texture->backgroundnmaptexture             ));
3170                 if (r_cg_permutation->fp_Texture_SecondaryColor ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryColor , R_GetTexture(rsurface.texture->backgroundbasetexture             ));
3171                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryGloss , R_GetTexture(rsurface.texture->backgroundglosstexture            ));
3172                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryGlow  , R_GetTexture(rsurface.texture->backgroundglowtexture             ));
3173                 if (r_cg_permutation->fp_Texture_Pants          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Pants          , R_GetTexture(rsurface.texture->pantstexture                      ));
3174                 if (r_cg_permutation->fp_Texture_Shirt          ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Shirt          , R_GetTexture(rsurface.texture->shirttexture                      ));
3175                 if (r_cg_permutation->fp_Texture_FogMask        ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_FogMask        , R_GetTexture(r_texture_fogattenuation                            ));
3176                 if (r_cg_permutation->fp_Texture_Lightmap       ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Lightmap       , R_GetTexture(r_texture_white                                     ));
3177                 if (r_cg_permutation->fp_Texture_Deluxemap      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Deluxemap      , R_GetTexture(r_texture_blanknormalmap                            ));
3178                 if (r_cg_permutation->fp_Texture_Attenuation    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Attenuation    , R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3179                 if (r_cg_permutation->fp_Texture_Refraction     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Refraction     , R_GetTexture(r_texture_white                                     ));
3180                 if (r_cg_permutation->fp_Texture_Reflection     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Reflection     , R_GetTexture(r_texture_white                                     ));
3181                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDepth    , R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3182                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3183                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDiffuse  , R_GetTexture(r_shadow_prepasslightingdiffusetexture              ));
3184                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenSpecular , R_GetTexture(r_shadow_prepasslightingspeculartexture             ));
3185                 if (rsurface.rtlight)
3186                 {
3187                         if (r_cg_permutation->fp_Texture_Cube       ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Cube           , R_GetTexture(rsurface.rtlight->currentcubemap                    ));
3188                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapRect  , R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3189                         if (r_shadow_usingshadowmapcube)
3190                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapCube  , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
3191                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMap2D    , R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3192                         if (r_cg_permutation->fp_Texture_CubeProjection ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture                      ));
3193                 }
3194
3195                 CHECKGLERROR
3196 #endif
3197                 break;
3198         case RENDERPATH_GL13:
3199         case RENDERPATH_GL11:
3200                 break;
3201         }
3202 }
3203
3204 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3205 {
3206         // select a permutation of the lighting shader appropriate to this
3207         // combination of texture, entity, light source, and fogging, only use the
3208         // minimum features necessary to avoid wasting rendering time in the
3209         // fragment shader on features that are not being used
3210         unsigned int permutation = 0;
3211         unsigned int mode = 0;
3212         const float *lightcolorbase = rtlight->currentcolor;
3213         float ambientscale = rtlight->ambientscale;
3214         float diffusescale = rtlight->diffusescale;
3215         float specularscale = rtlight->specularscale;
3216         // this is the location of the light in view space
3217         vec3_t viewlightorigin;
3218         // this transforms from view space (camera) to light space (cubemap)
3219         matrix4x4_t viewtolight;
3220         matrix4x4_t lighttoview;
3221         float viewtolight16f[16];
3222         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3223         // light source
3224         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3225         if (rtlight->currentcubemap != r_texture_whitecube)
3226                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3227         if (diffusescale > 0)
3228                 permutation |= SHADERPERMUTATION_DIFFUSE;
3229         if (specularscale > 0)
3230         {
3231                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3232                 if (r_shadow_glossexact.integer)
3233                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
3234         }
3235         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
3236         {
3237                 if (r_shadow_usingshadowmaprect)
3238                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
3239                 if (r_shadow_usingshadowmap2d)
3240                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3241                 if (r_shadow_usingshadowmapcube)
3242                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
3243                 else if(r_shadow_shadowmapvsdct)
3244                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3245
3246                 if (r_shadow_shadowmapsampler)
3247                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3248                 if (r_shadow_shadowmappcf > 1)
3249                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3250                 else if (r_shadow_shadowmappcf)
3251                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3252         }
3253         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3254         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3255         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3256         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3257         switch(vid.renderpath)
3258         {
3259         case RENDERPATH_GL20:
3260                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3261                 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3262                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3263                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3264                 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);
3265                 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);
3266                 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);
3267                 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]);
3268                 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]);
3269                 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));
3270                 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]);
3271
3272                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       ,          R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3273                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH    , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3274                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3275                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBindAll(GL20TU_CUBE           , 0, 0,    R_GetTexture(rsurface.rtlight->currentcubemap                    ), 0);
3276                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT  , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3277                 if (r_shadow_usingshadowmapcube)
3278                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE  , 0, 0,    R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
3279                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       ,          R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3280                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0,    R_GetTexture(r_shadow_shadowmapvsdcttexture                      ), 0);
3281                 break;
3282         case RENDERPATH_CGGL:
3283 #ifdef SUPPORTCG
3284                 R_SetupShader_SetPermutationCG(mode, permutation);
3285                 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);
3286                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3287                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);
3288                 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);
3289                 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);
3290                 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);
3291                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3292                 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]);
3293                 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));
3294                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3295
3296                 if (r_cg_permutation->fp_Texture_Attenuation      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Attenuation    , R_GetTexture(r_shadow_attenuationgradienttexture                 ));
3297                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDepth    , R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
3298                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
3299                 if (r_cg_permutation->fp_Texture_Cube             ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Cube           , R_GetTexture(rsurface.rtlight->currentcubemap                    ));
3300                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapRect  , R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
3301                 if (r_shadow_usingshadowmapcube)
3302                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapCube  , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
3303                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMap2D    , R_GetTexture(r_shadow_shadowmap2dtexture                         ));
3304                 if (r_cg_permutation->fp_Texture_CubeProjection   ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture                      ));
3305 #endif
3306                 break;
3307         case RENDERPATH_GL13:
3308         case RENDERPATH_GL11:
3309                 break;
3310         }
3311 }
3312
3313 #define SKINFRAME_HASH 1024
3314
3315 typedef struct
3316 {
3317         int loadsequence; // incremented each level change
3318         memexpandablearray_t array;
3319         skinframe_t *hash[SKINFRAME_HASH];
3320 }
3321 r_skinframe_t;
3322 r_skinframe_t r_skinframe;
3323
3324 void R_SkinFrame_PrepareForPurge(void)
3325 {
3326         r_skinframe.loadsequence++;
3327         // wrap it without hitting zero
3328         if (r_skinframe.loadsequence >= 200)
3329                 r_skinframe.loadsequence = 1;
3330 }
3331
3332 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3333 {
3334         if (!skinframe)
3335                 return;
3336         // mark the skinframe as used for the purging code
3337         skinframe->loadsequence = r_skinframe.loadsequence;
3338 }
3339
3340 void R_SkinFrame_Purge(void)
3341 {
3342         int i;
3343         skinframe_t *s;
3344         for (i = 0;i < SKINFRAME_HASH;i++)
3345         {
3346                 for (s = r_skinframe.hash[i];s;s = s->next)
3347                 {
3348                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3349                         {
3350                                 if (s->merged == s->base)
3351                                         s->merged = NULL;
3352                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3353                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3354                                 R_PurgeTexture(s->merged);s->merged = NULL;
3355                                 R_PurgeTexture(s->base  );s->base   = NULL;
3356                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3357                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3358                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3359                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3360                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3361                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3362                                 s->loadsequence = 0;
3363                         }
3364                 }
3365         }
3366 }
3367
3368 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3369         skinframe_t *item;
3370         char basename[MAX_QPATH];
3371
3372         Image_StripImageExtension(name, basename, sizeof(basename));
3373
3374         if( last == NULL ) {
3375                 int hashindex;
3376                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3377                 item = r_skinframe.hash[hashindex];
3378         } else {
3379                 item = last->next;
3380         }
3381
3382         // linearly search through the hash bucket
3383         for( ; item ; item = item->next ) {
3384                 if( !strcmp( item->basename, basename ) ) {
3385                         return item;
3386                 }
3387         }
3388         return NULL;
3389 }
3390
3391 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3392 {
3393         skinframe_t *item;
3394         int hashindex;
3395         char basename[MAX_QPATH];
3396
3397         Image_StripImageExtension(name, basename, sizeof(basename));
3398
3399         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3400         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3401                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3402                         break;
3403
3404         if (!item) {
3405                 rtexture_t *dyntexture;
3406                 // check whether its a dynamic texture
3407                 dyntexture = CL_GetDynTexture( basename );
3408                 if (!add && !dyntexture)
3409                         return NULL;
3410                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3411                 memset(item, 0, sizeof(*item));
3412                 strlcpy(item->basename, basename, sizeof(item->basename));
3413                 item->base = dyntexture; // either NULL or dyntexture handle
3414                 item->textureflags = textureflags;
3415                 item->comparewidth = comparewidth;
3416                 item->compareheight = compareheight;
3417                 item->comparecrc = comparecrc;
3418                 item->next = r_skinframe.hash[hashindex];
3419                 r_skinframe.hash[hashindex] = item;
3420         }
3421         else if( item->base == NULL )
3422         {
3423                 rtexture_t *dyntexture;
3424                 // check whether its a dynamic texture
3425                 // 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]
3426                 dyntexture = CL_GetDynTexture( basename );
3427                 item->base = dyntexture; // either NULL or dyntexture handle
3428         }
3429
3430         R_SkinFrame_MarkUsed(item);
3431         return item;
3432 }
3433
3434 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3435         { \
3436                 unsigned long long avgcolor[5], wsum; \
3437                 int pix, comp, w; \
3438                 avgcolor[0] = 0; \
3439                 avgcolor[1] = 0; \
3440                 avgcolor[2] = 0; \
3441                 avgcolor[3] = 0; \
3442                 avgcolor[4] = 0; \
3443                 wsum = 0; \
3444                 for(pix = 0; pix < cnt; ++pix) \
3445                 { \
3446                         w = 0; \
3447                         for(comp = 0; comp < 3; ++comp) \
3448                                 w += getpixel; \
3449                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3450                         { \
3451                                 ++wsum; \
3452                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3453                                 w = getpixel; \
3454                                 for(comp = 0; comp < 3; ++comp) \
3455                                         avgcolor[comp] += getpixel * w; \
3456                                 avgcolor[3] += w; \
3457                         } \
3458                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3459                         avgcolor[4] += getpixel; \
3460                 } \
3461                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3462                         avgcolor[3] = 1; \
3463                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3464                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3465                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3466                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3467         }
3468
3469 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3470 {
3471         int j;
3472         unsigned char *pixels;
3473         unsigned char *bumppixels;
3474         unsigned char *basepixels = NULL;
3475         int basepixels_width;
3476         int basepixels_height;
3477         skinframe_t *skinframe;
3478
3479         if (cls.state == ca_dedicated)
3480                 return NULL;
3481
3482         // return an existing skinframe if already loaded
3483         // if loading of the first image fails, don't make a new skinframe as it
3484         // would cause all future lookups of this to be missing
3485         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3486         if (skinframe && skinframe->base)
3487                 return skinframe;
3488
3489         basepixels = loadimagepixelsbgra(name, complain, true);
3490         if (basepixels == NULL)
3491                 return NULL;
3492
3493         if (developer_loading.integer)
3494                 Con_Printf("loading skin \"%s\"\n", name);
3495
3496         // we've got some pixels to store, so really allocate this new texture now
3497         if (!skinframe)
3498                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3499         skinframe->stain = NULL;
3500         skinframe->merged = NULL;
3501         skinframe->base = r_texture_notexture;
3502         skinframe->pants = NULL;
3503         skinframe->shirt = NULL;
3504         skinframe->nmap = r_texture_blanknormalmap;
3505         skinframe->gloss = NULL;
3506         skinframe->glow = NULL;
3507         skinframe->fog = NULL;
3508         skinframe->hasalpha = false;
3509
3510         basepixels_width = image_width;
3511         basepixels_height = image_height;
3512         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);
3513
3514         if (textureflags & TEXF_ALPHA)
3515         {
3516                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3517                 {
3518                         if (basepixels[j] < 255)
3519                         {
3520                                 skinframe->hasalpha = true;
3521                                 break;
3522                         }
3523                 }
3524                 if (r_loadfog && skinframe->hasalpha)
3525                 {
3526                         // has transparent pixels
3527                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3528                         for (j = 0;j < image_width * image_height * 4;j += 4)
3529                         {
3530                                 pixels[j+0] = 255;
3531                                 pixels[j+1] = 255;
3532                                 pixels[j+2] = 255;
3533                                 pixels[j+3] = basepixels[j+3];
3534                         }
3535                         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);
3536                         Mem_Free(pixels);
3537                 }
3538         }
3539
3540         R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3541         //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]);
3542
3543         // _norm is the name used by tenebrae and has been adopted as standard
3544         if (r_loadnormalmap)
3545         {
3546                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
3547                 {
3548                         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);
3549                         Mem_Free(pixels);
3550                         pixels = NULL;
3551                 }
3552                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
3553                 {
3554                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3555                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3556                         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);
3557                         Mem_Free(pixels);
3558                         Mem_Free(bumppixels);
3559                 }
3560                 else if (r_shadow_bumpscale_basetexture.value > 0)
3561                 {
3562                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3563                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3564                         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);
3565                         Mem_Free(pixels);
3566                 }
3567         }
3568         // _luma is supported for tenebrae compatibility
3569         // (I think it's a very stupid name, but oh well)
3570         // _glow is the preferred name
3571         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;}
3572         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;}
3573         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;}
3574         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;}
3575
3576         if (basepixels)
3577                 Mem_Free(basepixels);
3578
3579         return skinframe;
3580 }
3581
3582 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3583 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3584 {
3585         int i;
3586         unsigned char *temp1, *temp2;
3587         skinframe_t *skinframe;
3588
3589         if (cls.state == ca_dedicated)
3590                 return NULL;
3591
3592         // if already loaded just return it, otherwise make a new skinframe
3593         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3594         if (skinframe && skinframe->base)
3595                 return skinframe;
3596
3597         skinframe->stain = NULL;
3598         skinframe->merged = NULL;
3599         skinframe->base = r_texture_notexture;
3600         skinframe->pants = NULL;
3601         skinframe->shirt = NULL;
3602         skinframe->nmap = r_texture_blanknormalmap;
3603         skinframe->gloss = NULL;
3604         skinframe->glow = NULL;
3605         skinframe->fog = NULL;
3606         skinframe->hasalpha = false;
3607
3608         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3609         if (!skindata)
3610                 return NULL;
3611
3612         if (developer_loading.integer)
3613                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3614
3615         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3616         {
3617                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3618                 temp2 = temp1 + width * height * 4;
3619                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3620                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3621                 Mem_Free(temp1);
3622         }
3623         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
3624         if (textureflags & TEXF_ALPHA)
3625         {
3626                 for (i = 3;i < width * height * 4;i += 4)
3627                 {
3628                         if (skindata[i] < 255)
3629                         {
3630                                 skinframe->hasalpha = true;
3631                                 break;
3632                         }
3633                 }
3634                 if (r_loadfog && skinframe->hasalpha)
3635                 {
3636                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3637                         memcpy(fogpixels, skindata, width * height * 4);
3638                         for (i = 0;i < width * height * 4;i += 4)
3639                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3640                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
3641                         Mem_Free(fogpixels);
3642                 }
3643         }
3644
3645         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3646         //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]);
3647
3648         return skinframe;
3649 }
3650
3651 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3652 {
3653         int i;
3654         int featuresmask;
3655         skinframe_t *skinframe;
3656
3657         if (cls.state == ca_dedicated)
3658                 return NULL;
3659
3660         // if already loaded just return it, otherwise make a new skinframe
3661         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3662         if (skinframe && skinframe->base)
3663                 return skinframe;
3664
3665         skinframe->stain = NULL;
3666         skinframe->merged = NULL;
3667         skinframe->base = r_texture_notexture;
3668         skinframe->pants = NULL;
3669         skinframe->shirt = NULL;
3670         skinframe->nmap = r_texture_blanknormalmap;
3671         skinframe->gloss = NULL;
3672         skinframe->glow = NULL;
3673         skinframe->fog = NULL;
3674         skinframe->hasalpha = false;
3675
3676         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3677         if (!skindata)
3678                 return NULL;
3679
3680         if (developer_loading.integer)
3681                 Con_Printf("loading quake skin \"%s\"\n", name);
3682
3683         // 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)
3684         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
3685         memcpy(skinframe->qpixels, skindata, width*height);
3686         skinframe->qwidth = width;
3687         skinframe->qheight = height;
3688
3689         featuresmask = 0;
3690         for (i = 0;i < width * height;i++)
3691                 featuresmask |= palette_featureflags[skindata[i]];
3692
3693         skinframe->hasalpha = false;
3694         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3695         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3696         skinframe->qgeneratemerged = true;
3697         skinframe->qgeneratebase = skinframe->qhascolormapping;
3698         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3699
3700         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3701         //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]);
3702
3703         return skinframe;
3704 }
3705
3706 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3707 {
3708         int width;
3709         int height;
3710         unsigned char *skindata;
3711
3712         if (!skinframe->qpixels)
3713                 return;
3714
3715         if (!skinframe->qhascolormapping)
3716                 colormapped = false;
3717
3718         if (colormapped)
3719         {
3720                 if (!skinframe->qgeneratebase)
3721                         return;
3722         }
3723         else
3724         {
3725                 if (!skinframe->qgeneratemerged)
3726                         return;
3727         }
3728
3729         width = skinframe->qwidth;
3730         height = skinframe->qheight;
3731         skindata = skinframe->qpixels;
3732
3733         if (skinframe->qgeneratenmap)
3734         {
3735                 unsigned char *temp1, *temp2;
3736                 skinframe->qgeneratenmap = false;
3737                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3738                 temp2 = temp1 + width * height * 4;
3739                 // use either a custom palette or the quake palette
3740                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3741                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3742                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3743                 Mem_Free(temp1);
3744         }
3745
3746         if (skinframe->qgenerateglow)
3747         {
3748                 skinframe->qgenerateglow = false;
3749                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
3750         }
3751
3752         if (colormapped)
3753         {
3754                 skinframe->qgeneratebase = false;
3755                 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);
3756                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
3757                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
3758         }
3759         else
3760         {
3761                 skinframe->qgeneratemerged = false;
3762                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3763         }
3764
3765         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3766         {
3767                 Mem_Free(skinframe->qpixels);
3768                 skinframe->qpixels = NULL;
3769         }
3770 }
3771
3772 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)
3773 {
3774         int i;
3775         skinframe_t *skinframe;
3776
3777         if (cls.state == ca_dedicated)
3778                 return NULL;
3779
3780         // if already loaded just return it, otherwise make a new skinframe
3781         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3782         if (skinframe && skinframe->base)
3783                 return skinframe;
3784
3785         skinframe->stain = NULL;
3786         skinframe->merged = NULL;
3787         skinframe->base = r_texture_notexture;
3788         skinframe->pants = NULL;
3789         skinframe->shirt = NULL;
3790         skinframe->nmap = r_texture_blanknormalmap;
3791         skinframe->gloss = NULL;
3792         skinframe->glow = NULL;
3793         skinframe->fog = NULL;
3794         skinframe->hasalpha = false;
3795
3796         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3797         if (!skindata)
3798                 return NULL;
3799
3800         if (developer_loading.integer)
3801                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3802
3803         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3804         if (textureflags & TEXF_ALPHA)
3805         {
3806                 for (i = 0;i < width * height;i++)
3807                 {
3808                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3809                         {
3810                                 skinframe->hasalpha = true;
3811                                 break;
3812                         }
3813                 }
3814                 if (r_loadfog && skinframe->hasalpha)
3815                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3816         }
3817
3818         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3819         //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]);
3820
3821         return skinframe;
3822 }
3823
3824 skinframe_t *R_SkinFrame_LoadMissing(void)
3825 {
3826         skinframe_t *skinframe;
3827
3828         if (cls.state == ca_dedicated)
3829                 return NULL;
3830
3831         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3832         skinframe->stain = NULL;
3833         skinframe->merged = NULL;
3834         skinframe->base = r_texture_notexture;
3835         skinframe->pants = NULL;
3836         skinframe->shirt = NULL;
3837         skinframe->nmap = r_texture_blanknormalmap;
3838         skinframe->gloss = NULL;
3839         skinframe->glow = NULL;
3840         skinframe->fog = NULL;
3841         skinframe->hasalpha = false;
3842
3843         skinframe->avgcolor[0] = rand() / RAND_MAX;
3844         skinframe->avgcolor[1] = rand() / RAND_MAX;
3845         skinframe->avgcolor[2] = rand() / RAND_MAX;
3846         skinframe->avgcolor[3] = 1;
3847
3848         return skinframe;
3849 }
3850
3851 void R_Main_FreeViewCache(void)
3852 {
3853         if (r_refdef.viewcache.entityvisible)
3854                 Mem_Free(r_refdef.viewcache.entityvisible);
3855         if (r_refdef.viewcache.world_pvsbits)
3856                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3857         if (r_refdef.viewcache.world_leafvisible)
3858                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3859         if (r_refdef.viewcache.world_surfacevisible)
3860                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3861         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3862 }
3863
3864 void R_Main_ResizeViewCache(void)
3865 {
3866         int numentities = r_refdef.scene.numentities;
3867         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3868         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3869         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3870         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3871         if (r_refdef.viewcache.maxentities < numentities)
3872         {
3873                 r_refdef.viewcache.maxentities = numentities;
3874                 if (r_refdef.viewcache.entityvisible)
3875                         Mem_Free(r_refdef.viewcache.entityvisible);
3876                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3877         }
3878         if (r_refdef.viewcache.world_numclusters != numclusters)
3879         {
3880                 r_refdef.viewcache.world_numclusters = numclusters;
3881                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3882                 if (r_refdef.viewcache.world_pvsbits)
3883                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3884                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3885         }
3886         if (r_refdef.viewcache.world_numleafs != numleafs)
3887         {
3888                 r_refdef.viewcache.world_numleafs = numleafs;
3889                 if (r_refdef.viewcache.world_leafvisible)
3890                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3891                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3892         }
3893         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3894         {
3895                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3896                 if (r_refdef.viewcache.world_surfacevisible)
3897                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3898                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3899         }
3900 }
3901
3902 extern rtexture_t *loadingscreentexture;
3903 void gl_main_start(void)
3904 {
3905         loadingscreentexture = NULL;
3906         r_texture_blanknormalmap = NULL;
3907         r_texture_white = NULL;
3908         r_texture_grey128 = NULL;
3909         r_texture_black = NULL;
3910         r_texture_whitecube = NULL;
3911         r_texture_normalizationcube = NULL;
3912         r_texture_fogattenuation = NULL;
3913         r_texture_gammaramps = NULL;
3914
3915         switch(vid.renderpath)
3916         {
3917         case RENDERPATH_GL20:
3918         case RENDERPATH_CGGL:
3919                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3920                 Cvar_SetValueQuick(&gl_combine, 1);
3921                 Cvar_SetValueQuick(&r_glsl, 1);
3922                 r_loadnormalmap = true;
3923                 r_loadgloss = true;
3924                 r_loadfog = false;
3925                 break;
3926         case RENDERPATH_GL13:
3927                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3928                 Cvar_SetValueQuick(&gl_combine, 1);
3929                 Cvar_SetValueQuick(&r_glsl, 0);
3930                 r_loadnormalmap = false;
3931                 r_loadgloss = false;
3932                 r_loadfog = true;
3933                 break;
3934         case RENDERPATH_GL11:
3935                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3936                 Cvar_SetValueQuick(&gl_combine, 0);
3937                 Cvar_SetValueQuick(&r_glsl, 0);
3938                 r_loadnormalmap = false;
3939                 r_loadgloss = false;
3940                 r_loadfog = true;
3941                 break;
3942         }
3943
3944         R_AnimCache_Free();
3945         R_FrameData_Reset();
3946
3947         r_numqueries = 0;
3948         r_maxqueries = 0;
3949         memset(r_queries, 0, sizeof(r_queries));
3950
3951         r_qwskincache = NULL;
3952         r_qwskincache_size = 0;
3953
3954         // set up r_skinframe loading system for textures
3955         memset(&r_skinframe, 0, sizeof(r_skinframe));
3956         r_skinframe.loadsequence = 1;
3957         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3958
3959         r_main_texturepool = R_AllocTexturePool();
3960         R_BuildBlankTextures();
3961         R_BuildNoTexture();
3962         if (vid.support.arb_texture_cube_map)
3963         {
3964                 R_BuildWhiteCube();
3965                 R_BuildNormalizationCube();
3966         }
3967         r_texture_fogattenuation = NULL;
3968         r_texture_gammaramps = NULL;
3969         //r_texture_fogintensity = NULL;
3970         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3971         memset(&r_waterstate, 0, sizeof(r_waterstate));
3972         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3973         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3974 #ifdef SUPPORTCG
3975         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
3976         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
3977 #endif
3978         memset(&r_svbsp, 0, sizeof (r_svbsp));
3979
3980         r_refdef.fogmasktable_density = 0;
3981 }
3982
3983 void gl_main_shutdown(void)
3984 {
3985         R_AnimCache_Free();
3986         R_FrameData_Reset();
3987
3988         R_Main_FreeViewCache();
3989
3990         if (r_maxqueries)
3991                 qglDeleteQueriesARB(r_maxqueries, r_queries);
3992
3993         r_numqueries = 0;
3994         r_maxqueries = 0;
3995         memset(r_queries, 0, sizeof(r_queries));
3996
3997         r_qwskincache = NULL;
3998         r_qwskincache_size = 0;
3999
4000         // clear out the r_skinframe state
4001         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4002         memset(&r_skinframe, 0, sizeof(r_skinframe));
4003
4004         if (r_svbsp.nodes)
4005                 Mem_Free(r_svbsp.nodes);
4006         memset(&r_svbsp, 0, sizeof (r_svbsp));
4007         R_FreeTexturePool(&r_main_texturepool);
4008         loadingscreentexture = NULL;
4009         r_texture_blanknormalmap = NULL;
4010         r_texture_white = NULL;
4011         r_texture_grey128 = NULL;
4012         r_texture_black = NULL;
4013         r_texture_whitecube = NULL;
4014         r_texture_normalizationcube = NULL;
4015         r_texture_fogattenuation = NULL;
4016         r_texture_gammaramps = NULL;
4017         //r_texture_fogintensity = NULL;
4018         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4019         memset(&r_waterstate, 0, sizeof(r_waterstate));
4020         R_GLSL_Restart_f();
4021 }
4022
4023 extern void CL_ParseEntityLump(char *entitystring);
4024 void gl_main_newmap(void)
4025 {
4026         // FIXME: move this code to client
4027         int l;
4028         char *entities, entname[MAX_QPATH];
4029         if (r_qwskincache)
4030                 Mem_Free(r_qwskincache);
4031         r_qwskincache = NULL;
4032         r_qwskincache_size = 0;
4033         if (cl.worldmodel)
4034         {
4035                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
4036                 l = (int)strlen(entname) - 4;
4037                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
4038                 {
4039                         memcpy(entname + l, ".ent", 5);
4040                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4041                         {
4042                                 CL_ParseEntityLump(entities);
4043                                 Mem_Free(entities);
4044                                 return;
4045                         }
4046                 }
4047                 if (cl.worldmodel->brush.entities)
4048                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4049         }
4050         R_Main_FreeViewCache();
4051
4052         R_FrameData_Reset();
4053 }
4054
4055 void GL_Main_Init(void)
4056 {
4057         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4058
4059         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4060         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4061         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4062         if (gamemode == GAME_NEHAHRA)
4063         {
4064                 Cvar_RegisterVariable (&gl_fogenable);
4065                 Cvar_RegisterVariable (&gl_fogdensity);
4066                 Cvar_RegisterVariable (&gl_fogred);
4067                 Cvar_RegisterVariable (&gl_foggreen);
4068                 Cvar_RegisterVariable (&gl_fogblue);
4069                 Cvar_RegisterVariable (&gl_fogstart);
4070                 Cvar_RegisterVariable (&gl_fogend);
4071                 Cvar_RegisterVariable (&gl_skyclip);
4072         }
4073         Cvar_RegisterVariable(&r_motionblur);
4074         Cvar_RegisterVariable(&r_motionblur_maxblur);
4075         Cvar_RegisterVariable(&r_motionblur_bmin);
4076         Cvar_RegisterVariable(&r_motionblur_vmin);
4077         Cvar_RegisterVariable(&r_motionblur_vmax);
4078         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4079         Cvar_RegisterVariable(&r_motionblur_randomize);
4080         Cvar_RegisterVariable(&r_damageblur);
4081         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4082         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4083         Cvar_RegisterVariable(&r_equalize_entities_by);
4084         Cvar_RegisterVariable(&r_equalize_entities_to);
4085         Cvar_RegisterVariable(&r_depthfirst);
4086         Cvar_RegisterVariable(&r_useinfinitefarclip);
4087         Cvar_RegisterVariable(&r_farclip_base);
4088         Cvar_RegisterVariable(&r_farclip_world);
4089         Cvar_RegisterVariable(&r_nearclip);
4090         Cvar_RegisterVariable(&r_showbboxes);
4091         Cvar_RegisterVariable(&r_showsurfaces);
4092         Cvar_RegisterVariable(&r_showtris);
4093         Cvar_RegisterVariable(&r_shownormals);
4094         Cvar_RegisterVariable(&r_showlighting);
4095         Cvar_RegisterVariable(&r_showshadowvolumes);
4096         Cvar_RegisterVariable(&r_showcollisionbrushes);
4097         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4098         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4099         Cvar_RegisterVariable(&r_showdisabledepthtest);
4100         Cvar_RegisterVariable(&r_drawportals);
4101         Cvar_RegisterVariable(&r_drawentities);
4102         Cvar_RegisterVariable(&r_cullentities_trace);
4103         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4104         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4105         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4106         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4107         Cvar_RegisterVariable(&r_drawviewmodel);
4108         Cvar_RegisterVariable(&r_speeds);
4109         Cvar_RegisterVariable(&r_fullbrights);
4110         Cvar_RegisterVariable(&r_wateralpha);
4111         Cvar_RegisterVariable(&r_dynamic);
4112         Cvar_RegisterVariable(&r_fullbright);
4113         Cvar_RegisterVariable(&r_shadows);
4114         Cvar_RegisterVariable(&r_shadows_darken);
4115         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4116         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4117         Cvar_RegisterVariable(&r_shadows_throwdistance);
4118         Cvar_RegisterVariable(&r_shadows_throwdirection);
4119         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4120         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4121         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4122         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4123         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4124         Cvar_RegisterVariable(&r_fog_exp2);
4125         Cvar_RegisterVariable(&r_drawfog);
4126         Cvar_RegisterVariable(&r_transparentdepthmasking);
4127         Cvar_RegisterVariable(&r_textureunits);
4128         Cvar_RegisterVariable(&gl_combine);
4129         Cvar_RegisterVariable(&r_glsl);
4130         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4131         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4132         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4133         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4134         Cvar_RegisterVariable(&r_glsl_postprocess);
4135         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4136         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4137         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4138         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4139         Cvar_RegisterVariable(&r_water);
4140         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4141         Cvar_RegisterVariable(&r_water_clippingplanebias);
4142         Cvar_RegisterVariable(&r_water_refractdistort);
4143         Cvar_RegisterVariable(&r_water_reflectdistort);
4144         Cvar_RegisterVariable(&r_lerpsprites);
4145         Cvar_RegisterVariable(&r_lerpmodels);
4146         Cvar_RegisterVariable(&r_lerplightstyles);
4147         Cvar_RegisterVariable(&r_waterscroll);
4148         Cvar_RegisterVariable(&r_bloom);
4149         Cvar_RegisterVariable(&r_bloom_colorscale);
4150         Cvar_RegisterVariable(&r_bloom_brighten);
4151         Cvar_RegisterVariable(&r_bloom_blur);
4152         Cvar_RegisterVariable(&r_bloom_resolution);
4153         Cvar_RegisterVariable(&r_bloom_colorexponent);
4154         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4155         Cvar_RegisterVariable(&r_hdr);
4156         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4157         Cvar_RegisterVariable(&r_hdr_glowintensity);
4158         Cvar_RegisterVariable(&r_hdr_range);
4159         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4160         Cvar_RegisterVariable(&developer_texturelogging);
4161         Cvar_RegisterVariable(&gl_lightmaps);
4162         Cvar_RegisterVariable(&r_test);
4163         Cvar_RegisterVariable(&r_batchmode);
4164         Cvar_RegisterVariable(&r_glsl_saturation);
4165         Cvar_RegisterVariable(&r_framedatasize);
4166         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4167                 Cvar_SetValue("r_fullbrights", 0);
4168         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
4169
4170         Cvar_RegisterVariable(&r_track_sprites);
4171         Cvar_RegisterVariable(&r_track_sprites_flags);
4172         Cvar_RegisterVariable(&r_track_sprites_scalew);
4173         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4174 }
4175
4176 extern void R_Textures_Init(void);
4177 extern void GL_Draw_Init(void);
4178 extern void GL_Main_Init(void);
4179 extern void R_Shadow_Init(void);
4180 extern void R_Sky_Init(void);
4181 extern void GL_Surf_Init(void);
4182 extern void R_Particles_Init(void);
4183 extern void R_Explosion_Init(void);
4184 extern void gl_backend_init(void);
4185 extern void Sbar_Init(void);
4186 extern void R_LightningBeams_Init(void);
4187 extern void Mod_RenderInit(void);
4188
4189 void Render_Init(void)
4190 {
4191         gl_backend_init();
4192         R_Textures_Init();
4193         GL_Main_Init();
4194         GL_Draw_Init();
4195         R_Shadow_Init();
4196         R_Sky_Init();
4197         GL_Surf_Init();
4198         Sbar_Init();
4199         R_Particles_Init();
4200         R_Explosion_Init();
4201         R_LightningBeams_Init();
4202         Mod_RenderInit();
4203 }
4204
4205 /*
4206 ===============
4207 GL_Init
4208 ===============
4209 */
4210 extern char *ENGINE_EXTENSIONS;
4211 void GL_Init (void)
4212 {
4213         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4214         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4215         gl_version = (const char *)qglGetString(GL_VERSION);
4216         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4217
4218         if (!gl_extensions)
4219                 gl_extensions = "";
4220         if (!gl_platformextensions)
4221                 gl_platformextensions = "";
4222
4223         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4224         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4225         Con_Printf("GL_VERSION: %s\n", gl_version);
4226         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4227         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4228
4229         VID_CheckExtensions();
4230
4231         // LordHavoc: report supported extensions
4232         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4233
4234         // clear to black (loading plaque will be seen over this)
4235         CHECKGLERROR
4236         qglClearColor(0,0,0,1);CHECKGLERROR
4237         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
4238 }
4239
4240 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4241 {
4242         int i;
4243         mplane_t *p;
4244         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4245         {
4246                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4247                 if (i == 4)
4248                         continue;
4249                 p = r_refdef.view.frustum + i;
4250                 switch(p->signbits)
4251                 {
4252                 default:
4253                 case 0:
4254                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4255                                 return true;
4256                         break;
4257                 case 1:
4258                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4259                                 return true;
4260                         break;
4261                 case 2:
4262                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4263                                 return true;
4264                         break;
4265                 case 3:
4266                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4267                                 return true;
4268                         break;
4269                 case 4:
4270                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4271                                 return true;
4272                         break;
4273                 case 5:
4274                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4275                                 return true;
4276                         break;
4277                 case 6:
4278                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4279                                 return true;
4280                         break;
4281                 case 7:
4282                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4283                                 return true;
4284                         break;
4285                 }
4286         }
4287         return false;
4288 }
4289
4290 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4291 {
4292         int i;
4293         const mplane_t *p;
4294         for (i = 0;i < numplanes;i++)
4295         {
4296                 p = planes + i;
4297                 switch(p->signbits)
4298                 {
4299                 default:
4300                 case 0:
4301                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4302                                 return true;
4303                         break;
4304                 case 1:
4305                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4306                                 return true;
4307                         break;
4308                 case 2:
4309                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4310                                 return true;
4311                         break;
4312                 case 3:
4313                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4314                                 return true;
4315                         break;
4316                 case 4:
4317                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4318                                 return true;
4319                         break;
4320                 case 5:
4321                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4322                                 return true;
4323                         break;
4324                 case 6:
4325                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4326                                 return true;
4327                         break;
4328                 case 7:
4329                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4330                                 return true;
4331                         break;
4332                 }
4333         }
4334         return false;
4335 }
4336
4337 //==================================================================================
4338
4339 // LordHavoc: this stores temporary data used within the same frame
4340
4341 qboolean r_framedata_failed;
4342 static size_t r_framedata_size;
4343 static size_t r_framedata_current;
4344 static void *r_framedata_base;
4345
4346 void R_FrameData_Reset(void)
4347 {
4348         if (r_framedata_base);
4349                 Mem_Free(r_framedata_base);
4350         r_framedata_base = NULL;
4351         r_framedata_size = 0;
4352         r_framedata_current = 0;
4353         r_framedata_failed = false;
4354 }
4355
4356 void R_FrameData_NewFrame(void)
4357 {
4358         size_t wantedsize;
4359         if (r_framedata_failed)
4360                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
4361         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4362         wantedsize = bound(65536, wantedsize, 128*1024*1024);
4363         if (r_framedata_size != wantedsize)
4364         {
4365                 r_framedata_size = wantedsize;
4366                 if (r_framedata_base);
4367                         Mem_Free(r_framedata_base);
4368                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
4369         }
4370         r_framedata_current = 0;
4371         r_framedata_failed = false;
4372 }
4373
4374 void *R_FrameData_Alloc(size_t size)
4375 {
4376         void *data;
4377
4378         // align to 16 byte boundary
4379         size = (size + 15) & ~15;
4380         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
4381         r_framedata_current += size;
4382
4383         // check overflow
4384         if (r_framedata_current > r_framedata_size)
4385                 r_framedata_failed = true;
4386
4387         // return NULL on everything after a failure
4388         if (r_framedata_failed)
4389                 return NULL;
4390
4391         return data;
4392 }
4393
4394 void *R_FrameData_Store(size_t size, void *data)
4395 {
4396         void *d = R_FrameData_Alloc(size);
4397         if (d)
4398                 memcpy(d, data, size);
4399         return d;
4400 }
4401
4402 //==================================================================================
4403
4404 // LordHavoc: animcache originally written by Echon, rewritten since then
4405
4406 /**
4407  * Animation cache prevents re-generating mesh data for an animated model
4408  * multiple times in one frame for lighting, shadowing, reflections, etc.
4409  */
4410
4411 void R_AnimCache_Free(void)
4412 {
4413 }
4414
4415 void R_AnimCache_ClearCache(void)
4416 {
4417         int i;
4418         entity_render_t *ent;
4419
4420         for (i = 0;i < r_refdef.scene.numentities;i++)
4421         {
4422                 ent = r_refdef.scene.entities[i];
4423                 ent->animcache_vertex3f = NULL;
4424                 ent->animcache_normal3f = NULL;
4425                 ent->animcache_svector3f = NULL;
4426                 ent->animcache_tvector3f = NULL;
4427         }
4428 }
4429
4430 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4431 {
4432         dp_model_t *model = ent->model;
4433         int numvertices;
4434         // see if it's already cached this frame
4435         if (ent->animcache_vertex3f)
4436         {
4437                 // add normals/tangents if needed
4438                 if (wantnormals || wanttangents)
4439                 {
4440                         if (ent->animcache_normal3f)
4441                                 wantnormals = false;
4442                         if (ent->animcache_svector3f)
4443                                 wanttangents = false;
4444                         if (wantnormals || wanttangents)
4445                         {
4446                                 numvertices = model->surfmesh.num_vertices;
4447                                 if (wantnormals)
4448                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4449                                 if (wanttangents)
4450                                 {
4451                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4452                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4453                                 }
4454                                 if (!r_framedata_failed)
4455                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4456                         }
4457                 }
4458         }
4459         else
4460         {
4461                 // see if this ent is worth caching
4462                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4463                         return false;
4464                 // get some memory for this entity and generate mesh data
4465                 numvertices = model->surfmesh.num_vertices;
4466                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4467                 if (wantnormals)
4468                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4469                 if (wanttangents)
4470                 {
4471                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4472                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4473                 }
4474                 if (!r_framedata_failed)
4475                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4476         }
4477         return !r_framedata_failed;
4478 }
4479
4480 void R_AnimCache_CacheVisibleEntities(void)
4481 {
4482         int i;
4483         qboolean wantnormals = !r_showsurfaces.integer;
4484         qboolean wanttangents = !r_showsurfaces.integer;
4485
4486         switch(vid.renderpath)
4487         {
4488         case RENDERPATH_GL20:
4489         case RENDERPATH_CGGL:
4490                 break;
4491         case RENDERPATH_GL13:
4492         case RENDERPATH_GL11:
4493                 wanttangents = false;
4494                 break;
4495         }
4496
4497         // TODO: thread this
4498         // NOTE: R_PrepareRTLights() also caches entities
4499
4500         for (i = 0;i < r_refdef.scene.numentities;i++)
4501                 if (r_refdef.viewcache.entityvisible[i])
4502                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4503
4504         if (r_shadows.integer)
4505                 for (i = 0;i < r_refdef.scene.numentities;i++)
4506                         if (!r_refdef.viewcache.entityvisible[i])
4507                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
4508 }
4509
4510 //==================================================================================
4511
4512 static void R_View_UpdateEntityLighting (void)
4513 {
4514         int i;
4515         entity_render_t *ent;
4516         vec3_t tempdiffusenormal, avg;
4517         vec_t f, fa, fd, fdd;
4518
4519         for (i = 0;i < r_refdef.scene.numentities;i++)
4520         {
4521                 ent = r_refdef.scene.entities[i];
4522
4523                 // skip unseen models
4524                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
4525                         continue;
4526
4527                 // skip bsp models
4528                 if (ent->model && ent->model->brush.num_leafs)
4529                 {
4530                         // TODO: use modellight for r_ambient settings on world?
4531                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4532                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4533                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4534                         continue;
4535                 }
4536
4537                 // fetch the lighting from the worldmodel data
4538                 VectorClear(ent->modellight_ambient);
4539                 VectorClear(ent->modellight_diffuse);
4540                 VectorClear(tempdiffusenormal);
4541                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4542                 {
4543                         vec3_t org;
4544                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4545                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
4546                         if(ent->flags & RENDER_EQUALIZE)
4547                         {
4548                                 // first fix up ambient lighting...
4549                                 if(r_equalize_entities_minambient.value > 0)
4550                                 {
4551                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4552                                         if(fd > 0)
4553                                         {
4554                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4555                                                 if(fa < r_equalize_entities_minambient.value * fd)
4556                                                 {
4557                                                         // solve:
4558                                                         //   fa'/fd' = minambient
4559                                                         //   fa'+0.25*fd' = fa+0.25*fd
4560                                                         //   ...
4561                                                         //   fa' = fd' * minambient
4562                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4563                                                         //   ...
4564                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4565                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4566                                                         //   ...
4567                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4568                                                         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
4569                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4570                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4571                                                 }
4572                                         }
4573                                 }
4574
4575                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4576                                 {
4577                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
4578                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
4579                                         if(f > 0)
4580                                         {
4581                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
4582                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
4583                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4584                                         }
4585                                 }
4586                         }
4587                 }
4588                 else // highly rare
4589                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4590
4591                 // move the light direction into modelspace coordinates for lighting code
4592                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4593                 if(VectorLength2(ent->modellight_lightdir) == 0)
4594                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4595                 VectorNormalize(ent->modellight_lightdir);
4596         }
4597 }
4598
4599 #define MAX_LINEOFSIGHTTRACES 64
4600
4601 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4602 {
4603         int i;
4604         vec3_t boxmins, boxmaxs;
4605         vec3_t start;
4606         vec3_t end;
4607         dp_model_t *model = r_refdef.scene.worldmodel;
4608
4609         if (!model || !model->brush.TraceLineOfSight)
4610                 return true;
4611
4612         // expand the box a little
4613         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4614         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4615         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4616         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4617         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4618         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4619
4620         // try center
4621         VectorCopy(eye, start);
4622         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4623         if (model->brush.TraceLineOfSight(model, start, end))
4624                 return true;
4625
4626         // try various random positions
4627         for (i = 0;i < numsamples;i++)
4628         {
4629                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4630                 if (model->brush.TraceLineOfSight(model, start, end))
4631                         return true;
4632         }
4633
4634         return false;
4635 }
4636
4637
4638 static void R_View_UpdateEntityVisible (void)
4639 {
4640         int i;
4641         int renderimask;
4642         int samples;
4643         entity_render_t *ent;
4644
4645         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
4646         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4647         {
4648                 // worldmodel can check visibility
4649                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4650                 for (i = 0;i < r_refdef.scene.numentities;i++)
4651                 {
4652                         ent = r_refdef.scene.entities[i];
4653                         if (!(ent->flags & renderimask))
4654                         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)))
4655                         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))
4656                                 r_refdef.viewcache.entityvisible[i] = true;
4657                 }
4658                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
4659                 {
4660                         for (i = 0;i < r_refdef.scene.numentities;i++)
4661                         {
4662                                 ent = r_refdef.scene.entities[i];
4663                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4664                                 {
4665                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4666                                         if (samples < 0)
4667                                                 continue; // temp entities do pvs only
4668                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4669                                                 ent->last_trace_visibility = realtime;
4670                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4671                                                 r_refdef.viewcache.entityvisible[i] = 0;
4672                                 }
4673                         }
4674                 }
4675         }
4676         else
4677         {
4678                 // no worldmodel or it can't check visibility
4679                 for (i = 0;i < r_refdef.scene.numentities;i++)
4680                 {
4681                         ent = r_refdef.scene.entities[i];
4682                         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));
4683                 }
4684         }
4685 }
4686
4687 /// only used if skyrendermasked, and normally returns false
4688 int R_DrawBrushModelsSky (void)
4689 {
4690         int i, sky;
4691         entity_render_t *ent;
4692
4693         sky = false;
4694         for (i = 0;i < r_refdef.scene.numentities;i++)
4695         {
4696                 if (!r_refdef.viewcache.entityvisible[i])
4697                         continue;
4698                 ent = r_refdef.scene.entities[i];
4699                 if (!ent->model || !ent->model->DrawSky)
4700                         continue;
4701                 ent->model->DrawSky(ent);
4702                 sky = true;
4703         }
4704         return sky;
4705 }
4706
4707 static void R_DrawNoModel(entity_render_t *ent);
4708 static void R_DrawModels(void)
4709 {
4710         int i;
4711         entity_render_t *ent;
4712
4713         for (i = 0;i < r_refdef.scene.numentities;i++)
4714         {
4715                 if (!r_refdef.viewcache.entityvisible[i])
4716                         continue;
4717                 ent = r_refdef.scene.entities[i];
4718                 r_refdef.stats.entities++;
4719                 if (ent->model && ent->model->Draw != NULL)
4720                         ent->model->Draw(ent);
4721                 else
4722                         R_DrawNoModel(ent);
4723         }
4724 }
4725
4726 static void R_DrawModelsDepth(void)
4727 {
4728         int i;
4729         entity_render_t *ent;
4730
4731         for (i = 0;i < r_refdef.scene.numentities;i++)
4732         {
4733                 if (!r_refdef.viewcache.entityvisible[i])
4734                         continue;
4735                 ent = r_refdef.scene.entities[i];
4736                 if (ent->model && ent->model->DrawDepth != NULL)
4737                         ent->model->DrawDepth(ent);
4738         }
4739 }
4740
4741 static void R_DrawModelsDebug(void)
4742 {
4743         int i;
4744         entity_render_t *ent;
4745
4746         for (i = 0;i < r_refdef.scene.numentities;i++)
4747         {
4748                 if (!r_refdef.viewcache.entityvisible[i])
4749                         continue;
4750                 ent = r_refdef.scene.entities[i];
4751                 if (ent->model && ent->model->DrawDebug != NULL)
4752                         ent->model->DrawDebug(ent);
4753         }
4754 }
4755
4756 static void R_DrawModelsAddWaterPlanes(void)
4757 {
4758         int i;
4759         entity_render_t *ent;
4760
4761         for (i = 0;i < r_refdef.scene.numentities;i++)
4762         {
4763                 if (!r_refdef.viewcache.entityvisible[i])
4764                         continue;
4765                 ent = r_refdef.scene.entities[i];
4766                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4767                         ent->model->DrawAddWaterPlanes(ent);
4768         }
4769 }
4770
4771 static void R_View_SetFrustum(void)
4772 {
4773         int i;
4774         double slopex, slopey;
4775         vec3_t forward, left, up, origin;
4776
4777         // we can't trust r_refdef.view.forward and friends in reflected scenes
4778         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4779
4780 #if 0
4781         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4782         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4783         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4784         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4785         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4786         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4787         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4788         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4789         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4790         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4791         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4792         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4793 #endif
4794
4795 #if 0
4796         zNear = r_refdef.nearclip;
4797         nudge = 1.0 - 1.0 / (1<<23);
4798         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4799         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4800         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4801         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4802         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4803         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4804         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4805         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4806 #endif
4807
4808
4809
4810 #if 0
4811         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4812         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4813         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4814         r_refdef.view.frustum[0].dist = m[15] - m[12];
4815
4816         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4817         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4818         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4819         r_refdef.view.frustum[1].dist = m[15] + m[12];
4820
4821         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4822         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4823         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4824         r_refdef.view.frustum[2].dist = m[15] - m[13];
4825
4826         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4827         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4828         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4829         r_refdef.view.frustum[3].dist = m[15] + m[13];
4830
4831         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4832         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4833         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4834         r_refdef.view.frustum[4].dist = m[15] - m[14];
4835
4836         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4837         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4838         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4839         r_refdef.view.frustum[5].dist = m[15] + m[14];
4840 #endif
4841
4842         if (r_refdef.view.useperspective)
4843         {
4844                 slopex = 1.0 / r_refdef.view.frustum_x;
4845                 slopey = 1.0 / r_refdef.view.frustum_y;
4846                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4847                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
4848                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
4849                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
4850                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4851
4852                 // Leaving those out was a mistake, those were in the old code, and they
4853                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4854                 // I couldn't reproduce it after adding those normalizations. --blub
4855                 VectorNormalize(r_refdef.view.frustum[0].normal);
4856                 VectorNormalize(r_refdef.view.frustum[1].normal);
4857                 VectorNormalize(r_refdef.view.frustum[2].normal);
4858                 VectorNormalize(r_refdef.view.frustum[3].normal);
4859
4860                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4861                 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]);
4862                 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]);
4863                 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]);
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[3]);
4865
4866                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4867                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4868                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4869                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4870                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4871         }
4872         else
4873         {
4874                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4875                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4876                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4877                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4878                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4879                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4880                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4881                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4882                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4883                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4884         }
4885         r_refdef.view.numfrustumplanes = 5;
4886
4887         if (r_refdef.view.useclipplane)
4888         {
4889                 r_refdef.view.numfrustumplanes = 6;
4890                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4891         }
4892
4893         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4894                 PlaneClassify(r_refdef.view.frustum + i);
4895
4896         // LordHavoc: note to all quake engine coders, Quake had a special case
4897         // for 90 degrees which assumed a square view (wrong), so I removed it,
4898         // Quake2 has it disabled as well.
4899
4900         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4901         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4902         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4903         //PlaneClassify(&frustum[0]);
4904
4905         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4906         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4907         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4908         //PlaneClassify(&frustum[1]);
4909
4910         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4911         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4912         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4913         //PlaneClassify(&frustum[2]);
4914
4915         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4916         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4917         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4918         //PlaneClassify(&frustum[3]);
4919
4920         // nearclip plane
4921         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4922         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4923         //PlaneClassify(&frustum[4]);
4924 }
4925
4926 void R_View_Update(void)
4927 {
4928         R_Main_ResizeViewCache();
4929         R_View_SetFrustum();
4930         R_View_WorldVisibility(r_refdef.view.useclipplane);
4931         R_View_UpdateEntityVisible();
4932         R_View_UpdateEntityLighting();
4933 }
4934
4935 void R_SetupView(qboolean allowwaterclippingplane)
4936 {
4937         const float *customclipplane = NULL;
4938         float plane[4];
4939         if (r_refdef.view.useclipplane && allowwaterclippingplane)
4940         {
4941                 // LordHavoc: couldn't figure out how to make this approach the
4942                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4943                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4944                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4945                         dist = r_refdef.view.clipplane.dist;
4946                 plane[0] = r_refdef.view.clipplane.normal[0];
4947                 plane[1] = r_refdef.view.clipplane.normal[1];
4948                 plane[2] = r_refdef.view.clipplane.normal[2];
4949                 plane[3] = dist;
4950                 customclipplane = plane;
4951         }
4952
4953         if (!r_refdef.view.useperspective)
4954                 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);
4955         else if (vid.stencil && r_useinfinitefarclip.integer)
4956                 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);
4957         else
4958                 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);
4959         R_SetViewport(&r_refdef.view.viewport);
4960 }
4961
4962 void R_EntityMatrix(const matrix4x4_t *matrix)
4963 {
4964         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
4965         {
4966                 gl_modelmatrixchanged = false;
4967                 gl_modelmatrix = *matrix;
4968                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
4969                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
4970                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
4971                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
4972                 CHECKGLERROR
4973                 switch(vid.renderpath)
4974                 {
4975                 case RENDERPATH_GL20:
4976                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4977                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4978                         break;
4979                 case RENDERPATH_CGGL:
4980                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix >= 0) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4981                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4982                         break;
4983                 case RENDERPATH_GL13:
4984                 case RENDERPATH_GL11:
4985                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4986                         break;
4987                 }
4988         }
4989 }
4990
4991 void R_ResetViewRendering2D(void)
4992 {
4993         r_viewport_t viewport;
4994         DrawQ_Finish();
4995
4996         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4997         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);
4998         R_SetViewport(&viewport);
4999         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5000         GL_Color(1, 1, 1, 1);
5001         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5002         GL_BlendFunc(GL_ONE, GL_ZERO);
5003         GL_AlphaTest(false);
5004         GL_ScissorTest(false);
5005         GL_DepthMask(false);
5006         GL_DepthRange(0, 1);
5007         GL_DepthTest(false);
5008         R_EntityMatrix(&identitymatrix);
5009         R_Mesh_ResetTextureState();
5010         GL_PolygonOffset(0, 0);
5011         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5012         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5013         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
5014         qglStencilMask(~0);CHECKGLERROR
5015         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
5016         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
5017         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
5018 }
5019
5020 void R_ResetViewRendering3D(void)
5021 {
5022         DrawQ_Finish();
5023
5024         R_SetupView(true);
5025         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5026         GL_Color(1, 1, 1, 1);
5027         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5028         GL_BlendFunc(GL_ONE, GL_ZERO);
5029         GL_AlphaTest(false);
5030         GL_ScissorTest(true);
5031         GL_DepthMask(true);
5032         GL_DepthRange(0, 1);
5033         GL_DepthTest(true);
5034         R_EntityMatrix(&identitymatrix);
5035         R_Mesh_ResetTextureState();
5036         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5037         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5038         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5039         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
5040         qglStencilMask(~0);CHECKGLERROR
5041         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
5042         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
5043         GL_CullFace(r_refdef.view.cullface_back);
5044 }
5045
5046 void R_RenderScene(void);
5047 void R_RenderWaterPlanes(void);
5048
5049 static void R_Water_StartFrame(void)
5050 {
5051         int i;
5052         int waterwidth, waterheight, texturewidth, textureheight;
5053         r_waterstate_waterplane_t *p;
5054
5055         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5056                 return;
5057
5058         switch(vid.renderpath)
5059         {
5060         case RENDERPATH_GL20:
5061         case RENDERPATH_CGGL:
5062                 break;
5063         case RENDERPATH_GL13:
5064         case RENDERPATH_GL11:
5065                 return;
5066         }
5067
5068         // set waterwidth and waterheight to the water resolution that will be
5069         // used (often less than the screen resolution for faster rendering)
5070         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5071         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5072
5073         // calculate desired texture sizes
5074         // can't use water if the card does not support the texture size
5075         if (!r_water.integer || r_showsurfaces.integer)
5076                 texturewidth = textureheight = waterwidth = waterheight = 0;
5077         else if (vid.support.arb_texture_non_power_of_two)
5078         {
5079                 texturewidth = waterwidth;
5080                 textureheight = waterheight;
5081         }
5082         else
5083         {
5084                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5085                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5086         }
5087
5088         // allocate textures as needed
5089         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
5090         {
5091                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5092                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5093                 {
5094                         if (p->texture_refraction)
5095                                 R_FreeTexture(p->texture_refraction);
5096                         p->texture_refraction = NULL;
5097                         if (p->texture_reflection)
5098                                 R_FreeTexture(p->texture_reflection);
5099                         p->texture_reflection = NULL;
5100                 }
5101                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5102                 r_waterstate.texturewidth = texturewidth;
5103                 r_waterstate.textureheight = textureheight;
5104         }
5105
5106         if (r_waterstate.texturewidth)
5107         {
5108                 r_waterstate.enabled = true;
5109
5110                 // when doing a reduced render (HDR) we want to use a smaller area
5111                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5112                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5113
5114                 // set up variables that will be used in shader setup
5115                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5116                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5117                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5118                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5119         }
5120
5121         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5122         r_waterstate.numwaterplanes = 0;
5123 }
5124
5125 void R_Water_AddWaterPlane(msurface_t *surface)
5126 {
5127         int triangleindex, planeindex;
5128         const int *e;
5129         vec3_t vert[3];
5130         vec3_t normal;
5131         vec3_t center;
5132         mplane_t plane;
5133         r_waterstate_waterplane_t *p;
5134         texture_t *t = R_GetCurrentTexture(surface->texture);
5135         // just use the first triangle with a valid normal for any decisions
5136         VectorClear(normal);
5137         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5138         {
5139                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5140                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5141                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5142                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5143                 if (VectorLength2(normal) >= 0.001)
5144                         break;
5145         }
5146
5147         VectorCopy(normal, plane.normal);
5148         VectorNormalize(plane.normal);
5149         plane.dist = DotProduct(vert[0], plane.normal);
5150         PlaneClassify(&plane);
5151         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5152         {
5153                 // skip backfaces (except if nocullface is set)
5154                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5155                         return;
5156                 VectorNegate(plane.normal, plane.normal);
5157                 plane.dist *= -1;
5158                 PlaneClassify(&plane);
5159         }
5160
5161
5162         // find a matching plane if there is one
5163         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5164                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5165                         break;
5166         if (planeindex >= r_waterstate.maxwaterplanes)
5167                 return; // nothing we can do, out of planes
5168
5169         // if this triangle does not fit any known plane rendered this frame, add one
5170         if (planeindex >= r_waterstate.numwaterplanes)
5171         {
5172                 // store the new plane
5173                 r_waterstate.numwaterplanes++;
5174                 p->plane = plane;
5175                 // clear materialflags and pvs
5176                 p->materialflags = 0;
5177                 p->pvsvalid = false;
5178         }
5179         // merge this surface's materialflags into the waterplane
5180         p->materialflags |= t->currentmaterialflags;
5181         // merge this surface's PVS into the waterplane
5182         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5183         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5184          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5185         {
5186                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5187                 p->pvsvalid = true;
5188         }
5189 }
5190
5191 static void R_Water_ProcessPlanes(void)
5192 {
5193         r_refdef_view_t originalview;
5194         r_refdef_view_t myview;
5195         int planeindex;
5196         r_waterstate_waterplane_t *p;
5197
5198         originalview = r_refdef.view;
5199
5200         // make sure enough textures are allocated
5201         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5202         {
5203                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5204                 {
5205                         if (!p->texture_refraction)
5206                                 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);
5207                         if (!p->texture_refraction)
5208                                 goto error;
5209                 }
5210
5211                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5212                 {
5213                         if (!p->texture_reflection)
5214                                 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);
5215                         if (!p->texture_reflection)
5216                                 goto error;
5217                 }
5218         }
5219
5220         // render views
5221         r_refdef.view = originalview;
5222         r_refdef.view.showdebug = false;
5223         r_refdef.view.width = r_waterstate.waterwidth;
5224         r_refdef.view.height = r_waterstate.waterheight;
5225         r_refdef.view.useclipplane = true;
5226         myview = r_refdef.view;
5227         r_waterstate.renderingscene = true;
5228         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5229         {
5230                 // render the normal view scene and copy into texture
5231                 // (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)
5232                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5233                 {
5234                         r_refdef.view = myview;
5235                         r_refdef.view.clipplane = p->plane;
5236                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5237                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5238                         PlaneClassify(&r_refdef.view.clipplane);
5239
5240                         R_ResetViewRendering3D();
5241                         R_ClearScreen(r_refdef.fogenabled);
5242                         R_View_Update();
5243                         R_RenderScene();
5244
5245                         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);
5246                 }
5247
5248                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5249                 {
5250                         r_refdef.view = myview;
5251                         // render reflected scene and copy into texture
5252                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5253                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5254                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5255                         r_refdef.view.clipplane = p->plane;
5256                         // reverse the cullface settings for this render
5257                         r_refdef.view.cullface_front = GL_FRONT;
5258                         r_refdef.view.cullface_back = GL_BACK;
5259                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5260                         {
5261                                 r_refdef.view.usecustompvs = true;
5262                                 if (p->pvsvalid)
5263                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5264                                 else
5265                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5266                         }
5267
5268                         R_ResetViewRendering3D();
5269                         R_ClearScreen(r_refdef.fogenabled);
5270                         R_View_Update();
5271                         R_RenderScene();
5272
5273                         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);
5274                 }
5275         }
5276         r_waterstate.renderingscene = false;
5277         r_refdef.view = originalview;
5278         R_ResetViewRendering3D();
5279         R_ClearScreen(r_refdef.fogenabled);
5280         R_View_Update();
5281         return;
5282 error:
5283         r_refdef.view = originalview;
5284         r_waterstate.renderingscene = false;
5285         Cvar_SetValueQuick(&r_water, 0);
5286         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5287         return;
5288 }
5289
5290 void R_Bloom_StartFrame(void)
5291 {
5292         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5293
5294         switch(vid.renderpath)
5295         {
5296         case RENDERPATH_GL20:
5297         case RENDERPATH_CGGL:
5298                 break;
5299         case RENDERPATH_GL13:
5300         case RENDERPATH_GL11:
5301                 return;
5302         }
5303
5304         // set bloomwidth and bloomheight to the bloom resolution that will be
5305         // used (often less than the screen resolution for faster rendering)
5306         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5307         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5308         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5309         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5310         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5311
5312         // calculate desired texture sizes
5313         if (vid.support.arb_texture_non_power_of_two)
5314         {
5315                 screentexturewidth = r_refdef.view.width;
5316                 screentextureheight = r_refdef.view.height;
5317                 bloomtexturewidth = r_bloomstate.bloomwidth;
5318                 bloomtextureheight = r_bloomstate.bloomheight;
5319         }
5320         else
5321         {
5322                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5323                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5324                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5325                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5326         }
5327
5328         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))
5329         {
5330                 Cvar_SetValueQuick(&r_hdr, 0);
5331                 Cvar_SetValueQuick(&r_bloom, 0);
5332                 Cvar_SetValueQuick(&r_motionblur, 0);
5333                 Cvar_SetValueQuick(&r_damageblur, 0);
5334         }
5335
5336         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)))
5337                 screentexturewidth = screentextureheight = 0;
5338         if (!r_hdr.integer && !r_bloom.integer)
5339                 bloomtexturewidth = bloomtextureheight = 0;
5340
5341         // allocate textures as needed
5342         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5343         {
5344                 if (r_bloomstate.texture_screen)
5345                         R_FreeTexture(r_bloomstate.texture_screen);
5346                 r_bloomstate.texture_screen = NULL;
5347                 r_bloomstate.screentexturewidth = screentexturewidth;
5348                 r_bloomstate.screentextureheight = screentextureheight;
5349                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5350                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
5351         }
5352         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5353         {
5354                 if (r_bloomstate.texture_bloom)
5355                         R_FreeTexture(r_bloomstate.texture_bloom);
5356                 r_bloomstate.texture_bloom = NULL;
5357                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5358                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5359                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5360                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
5361         }
5362
5363         // when doing a reduced render (HDR) we want to use a smaller area
5364         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5365         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5366         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5367         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5368         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5369
5370         // set up a texcoord array for the full resolution screen image
5371         // (we have to keep this around to copy back during final render)
5372         r_bloomstate.screentexcoord2f[0] = 0;
5373         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5374         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5375         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5376         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5377         r_bloomstate.screentexcoord2f[5] = 0;
5378         r_bloomstate.screentexcoord2f[6] = 0;
5379         r_bloomstate.screentexcoord2f[7] = 0;
5380
5381         // set up a texcoord array for the reduced resolution bloom image
5382         // (which will be additive blended over the screen image)
5383         r_bloomstate.bloomtexcoord2f[0] = 0;
5384         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5385         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5386         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5387         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5388         r_bloomstate.bloomtexcoord2f[5] = 0;
5389         r_bloomstate.bloomtexcoord2f[6] = 0;
5390         r_bloomstate.bloomtexcoord2f[7] = 0;
5391
5392         if (r_hdr.integer || r_bloom.integer)
5393         {
5394                 r_bloomstate.enabled = true;
5395                 r_bloomstate.hdr = r_hdr.integer != 0;
5396         }
5397
5398         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);
5399 }
5400
5401 void R_Bloom_CopyBloomTexture(float colorscale)
5402 {
5403         r_refdef.stats.bloom++;
5404
5405         // scale down screen texture to the bloom texture size
5406         CHECKGLERROR
5407         R_SetViewport(&r_bloomstate.viewport);
5408         GL_BlendFunc(GL_ONE, GL_ZERO);
5409         GL_Color(colorscale, colorscale, colorscale, 1);
5410         // TODO: optimize with multitexture or GLSL
5411         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5412         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5413         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5414         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5415
5416         // we now have a bloom image in the framebuffer
5417         // copy it into the bloom image texture for later processing
5418         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);
5419         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5420 }
5421
5422 void R_Bloom_CopyHDRTexture(void)
5423 {
5424         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);
5425         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5426 }
5427
5428 void R_Bloom_MakeTexture(void)
5429 {
5430         int x, range, dir;
5431         float xoffset, yoffset, r, brighten;
5432
5433         r_refdef.stats.bloom++;
5434
5435         R_ResetViewRendering2D();
5436         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5437         R_Mesh_ColorPointer(NULL, 0, 0);
5438
5439         // we have a bloom image in the framebuffer
5440         CHECKGLERROR
5441         R_SetViewport(&r_bloomstate.viewport);
5442
5443         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5444         {
5445                 x *= 2;
5446                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5447                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5448                 GL_Color(r, r, r, 1);
5449                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5450                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5451                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5452                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5453
5454                 // copy the vertically blurred bloom view to a texture
5455                 GL_ActiveTexture(0);
5456                 CHECKGLERROR
5457                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
5458                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5459         }
5460
5461         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5462         brighten = r_bloom_brighten.value;
5463         if (r_hdr.integer)
5464                 brighten *= r_hdr_range.value;
5465         brighten = sqrt(brighten);
5466         if(range >= 1)
5467                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5468         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5469         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
5470
5471         for (dir = 0;dir < 2;dir++)
5472         {
5473                 // blend on at multiple vertical offsets to achieve a vertical blur
5474                 // TODO: do offset blends using GLSL
5475                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5476                 GL_BlendFunc(GL_ONE, GL_ZERO);
5477                 for (x = -range;x <= range;x++)
5478                 {
5479                         if (!dir){xoffset = 0;yoffset = x;}
5480                         else {xoffset = x;yoffset = 0;}
5481                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5482                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5483                         // compute a texcoord array with the specified x and y offset
5484                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5485                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5486                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5487                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5488                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5489                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5490                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5491                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5492                         // this r value looks like a 'dot' particle, fading sharply to
5493                         // black at the edges
5494                         // (probably not realistic but looks good enough)
5495                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5496                         //r = brighten/(range*2+1);
5497                         r = brighten / (range * 2 + 1);
5498                         if(range >= 1)
5499                                 r *= (1 - x*x/(float)(range*range));
5500                         GL_Color(r, r, r, 1);
5501                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5502                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5503                         GL_BlendFunc(GL_ONE, GL_ONE);
5504                 }
5505
5506                 // copy the vertically blurred bloom view to a texture
5507                 GL_ActiveTexture(0);
5508                 CHECKGLERROR
5509                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
5510                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5511         }
5512
5513         // apply subtract last
5514         // (just like it would be in a GLSL shader)
5515         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
5516         {
5517                 GL_BlendFunc(GL_ONE, GL_ZERO);
5518                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5519                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5520                 GL_Color(1, 1, 1, 1);
5521                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5522                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5523
5524                 GL_BlendFunc(GL_ONE, GL_ONE);
5525                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
5526                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5527                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5528                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
5529                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5530                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5531                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
5532
5533                 // copy the darkened bloom view to a texture
5534                 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);
5535                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5536         }
5537 }
5538
5539 void R_HDR_RenderBloomTexture(void)
5540 {
5541         int oldwidth, oldheight;
5542         float oldcolorscale;
5543
5544         oldcolorscale = r_refdef.view.colorscale;
5545         oldwidth = r_refdef.view.width;
5546         oldheight = r_refdef.view.height;
5547         r_refdef.view.width = r_bloomstate.bloomwidth;
5548         r_refdef.view.height = r_bloomstate.bloomheight;
5549
5550         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5551         // TODO: add exposure compensation features
5552         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5553
5554         r_refdef.view.showdebug = false;
5555         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5556
5557         R_ResetViewRendering3D();
5558
5559         R_ClearScreen(r_refdef.fogenabled);
5560         if (r_timereport_active)
5561                 R_TimeReport("HDRclear");
5562
5563         R_View_Update();
5564         if (r_timereport_active)
5565                 R_TimeReport("visibility");
5566
5567         // only do secondary renders with HDR if r_hdr is 2 or higher
5568         r_waterstate.numwaterplanes = 0;
5569         if (r_waterstate.enabled && r_hdr.integer >= 2)
5570                 R_RenderWaterPlanes();
5571
5572         r_refdef.view.showdebug = true;
5573         R_RenderScene();
5574         r_waterstate.numwaterplanes = 0;
5575
5576         R_ResetViewRendering2D();
5577
5578         R_Bloom_CopyHDRTexture();
5579         R_Bloom_MakeTexture();
5580
5581         // restore the view settings
5582         r_refdef.view.width = oldwidth;
5583         r_refdef.view.height = oldheight;
5584         r_refdef.view.colorscale = oldcolorscale;
5585         r_frame++; // used only by R_GetCurrentTexture
5586
5587         R_ResetViewRendering3D();
5588
5589         R_ClearScreen(r_refdef.fogenabled);
5590         if (r_timereport_active)
5591                 R_TimeReport("viewclear");
5592 }
5593
5594 static void R_BlendView(void)
5595 {
5596         unsigned int permutation;
5597         float uservecs[4][4];
5598
5599         switch (vid.renderpath)
5600         {
5601         case RENDERPATH_GL20:
5602         case RENDERPATH_CGGL:
5603                 permutation =
5604                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5605                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5606                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5607                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5608                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5609
5610                 if (r_bloomstate.texture_screen)
5611                 {
5612                         // make sure the buffer is available
5613                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5614
5615                         R_ResetViewRendering2D();
5616                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5617                         R_Mesh_ColorPointer(NULL, 0, 0);
5618
5619                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5620                         {
5621                                 // declare variables
5622                                 float speed;
5623                                 static float avgspeed;
5624
5625                                 speed = VectorLength(cl.movement_velocity);
5626
5627                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5628                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5629
5630                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5631                                 speed = bound(0, speed, 1);
5632                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5633
5634                                 // calculate values into a standard alpha
5635                                 cl.motionbluralpha = 1 - exp(-
5636                                                 (
5637                                                  (r_motionblur.value * speed / 80)
5638                                                  +
5639                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5640                                                 )
5641                                                 /
5642                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5643                                            );
5644
5645                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5646                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5647                                 // apply the blur
5648                                 if (cl.motionbluralpha > 0)
5649                                 {
5650                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5651                                         GL_Color(1, 1, 1, cl.motionbluralpha);
5652                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5653                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5654                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5655                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5656                                 }
5657                         }
5658
5659                         // copy view into the screen texture
5660                         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);
5661                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5662                 }
5663                 else if (!r_bloomstate.texture_bloom)
5664                 {
5665                         // we may still have to do view tint...
5666                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
5667                         {
5668                                 // apply a color tint to the whole view
5669                                 R_ResetViewRendering2D();
5670                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5671                                 R_Mesh_ColorPointer(NULL, 0, 0);
5672                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5673                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5674                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5675                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5676                         }
5677                         break; // no screen processing, no bloom, skip it
5678                 }
5679
5680                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
5681                 {
5682                         // render simple bloom effect
5683                         // copy the screen and shrink it and darken it for the bloom process
5684                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
5685                         // make the bloom texture
5686                         R_Bloom_MakeTexture();
5687                 }
5688
5689 #if _MSC_VER >= 1400
5690 #define sscanf sscanf_s
5691 #endif
5692                 memset(uservecs, 0, sizeof(uservecs));
5693                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
5694                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
5695                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
5696                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
5697
5698                 R_ResetViewRendering2D();
5699                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5700                 R_Mesh_ColorPointer(NULL, 0, 0);
5701                 GL_Color(1, 1, 1, 1);
5702                 GL_BlendFunc(GL_ONE, GL_ZERO);
5703                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5704                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5705
5706                 switch(vid.renderpath)
5707                 {
5708                 case RENDERPATH_GL20:
5709                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
5710                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , R_GetTexture(r_bloomstate.texture_screen));
5711                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , R_GetTexture(r_bloomstate.texture_bloom ));
5712                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps       ));
5713                         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]);
5714                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
5715                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
5716                         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]);
5717                         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]);
5718                         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]);
5719                         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]);
5720                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
5721                         break;
5722                 case RENDERPATH_CGGL:
5723 #ifdef SUPPORTCG
5724                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
5725                         if (r_cg_permutation->fp_Texture_First     ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First     , R_GetTexture(r_bloomstate.texture_screen));
5726                         if (r_cg_permutation->fp_Texture_Second    ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second    , R_GetTexture(r_bloomstate.texture_bloom ));
5727                         if (r_cg_permutation->fp_Texture_GammaRamps) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_GammaRamps, R_GetTexture(r_texture_gammaramps       ));
5728                         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]);
5729                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);
5730                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
5731                         if (r_cg_permutation->fp_UserVec1          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
5732                         if (r_cg_permutation->fp_UserVec2          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
5733                         if (r_cg_permutation->fp_UserVec3          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
5734                         if (r_cg_permutation->fp_UserVec4          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
5735                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);
5736 #endif
5737                         break;
5738                 default:
5739                         break;
5740                 }
5741                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5742                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5743                 break;
5744         case RENDERPATH_GL13:
5745         case RENDERPATH_GL11:
5746                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
5747                 {
5748                         // apply a color tint to the whole view
5749                         R_ResetViewRendering2D();
5750                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5751                         R_Mesh_ColorPointer(NULL, 0, 0);
5752                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5753                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5754                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5755                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5756                 }
5757                 break;
5758         }
5759 }
5760
5761 matrix4x4_t r_waterscrollmatrix;
5762
5763 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
5764 {
5765         if (r_refdef.fog_density)
5766         {
5767                 r_refdef.fogcolor[0] = r_refdef.fog_red;
5768                 r_refdef.fogcolor[1] = r_refdef.fog_green;
5769                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5770
5771                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5772                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5773                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5774                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5775
5776                 {
5777                         vec3_t fogvec;
5778                         VectorCopy(r_refdef.fogcolor, fogvec);
5779                         //   color.rgb *= ContrastBoost * SceneBrightness;
5780                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5781                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5782                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5783                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5784                 }
5785         }
5786 }
5787
5788 void R_UpdateVariables(void)
5789 {
5790         R_Textures_Frame();
5791
5792         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
5793
5794         r_refdef.farclip = r_farclip_base.value;
5795         if (r_refdef.scene.worldmodel)
5796                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5797         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5798
5799         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5800                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5801         r_refdef.polygonfactor = 0;
5802         r_refdef.polygonoffset = 0;
5803         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5804         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5805
5806         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5807         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5808         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5809         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5810         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5811         if (r_showsurfaces.integer)
5812         {
5813                 r_refdef.scene.rtworld = false;
5814                 r_refdef.scene.rtworldshadows = false;
5815                 r_refdef.scene.rtdlight = false;
5816                 r_refdef.scene.rtdlightshadows = false;
5817                 r_refdef.lightmapintensity = 0;
5818         }
5819
5820         if (gamemode == GAME_NEHAHRA)
5821         {
5822                 if (gl_fogenable.integer)
5823                 {
5824                         r_refdef.oldgl_fogenable = true;
5825                         r_refdef.fog_density = gl_fogdensity.value;
5826                         r_refdef.fog_red = gl_fogred.value;
5827                         r_refdef.fog_green = gl_foggreen.value;
5828                         r_refdef.fog_blue = gl_fogblue.value;
5829                         r_refdef.fog_alpha = 1;
5830                         r_refdef.fog_start = 0;
5831                         r_refdef.fog_end = gl_skyclip.value;
5832                         r_refdef.fog_height = 1<<30;
5833                         r_refdef.fog_fadedepth = 128;
5834                 }
5835                 else if (r_refdef.oldgl_fogenable)
5836                 {
5837                         r_refdef.oldgl_fogenable = false;
5838                         r_refdef.fog_density = 0;
5839                         r_refdef.fog_red = 0;
5840                         r_refdef.fog_green = 0;
5841                         r_refdef.fog_blue = 0;
5842                         r_refdef.fog_alpha = 0;
5843                         r_refdef.fog_start = 0;
5844                         r_refdef.fog_end = 0;
5845                         r_refdef.fog_height = 1<<30;
5846                         r_refdef.fog_fadedepth = 128;
5847                 }
5848         }
5849
5850         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5851         r_refdef.fog_start = max(0, r_refdef.fog_start);
5852         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5853
5854         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5855
5856         if (r_refdef.fog_density && r_drawfog.integer)
5857         {
5858                 r_refdef.fogenabled = true;
5859                 // this is the point where the fog reaches 0.9986 alpha, which we
5860                 // consider a good enough cutoff point for the texture
5861                 // (0.9986 * 256 == 255.6)
5862                 if (r_fog_exp2.integer)
5863                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5864                 else
5865                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5866                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5867                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5868                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5869                 // fog color was already set
5870                 // update the fog texture
5871                 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)
5872                         R_BuildFogTexture();
5873         }
5874         else
5875                 r_refdef.fogenabled = false;
5876
5877         switch(vid.renderpath)
5878         {
5879         case RENDERPATH_GL20:
5880         case RENDERPATH_CGGL:
5881                 if(v_glslgamma.integer && !vid_gammatables_trivial)
5882                 {
5883                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5884                         {
5885                                 // build GLSL gamma texture
5886 #define RAMPWIDTH 256
5887                                 unsigned short ramp[RAMPWIDTH * 3];
5888                                 unsigned char rampbgr[RAMPWIDTH][4];
5889                                 int i;
5890
5891                                 r_texture_gammaramps_serial = vid_gammatables_serial;
5892
5893                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5894                                 for(i = 0; i < RAMPWIDTH; ++i)
5895                                 {
5896                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5897                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5898                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5899                                         rampbgr[i][3] = 0;
5900                                 }
5901                                 if (r_texture_gammaramps)
5902                                 {
5903                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5904                                 }
5905                                 else
5906                                 {
5907                                         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);
5908                                 }
5909                         }
5910                 }
5911                 else
5912                 {
5913                         // remove GLSL gamma texture
5914                 }
5915                 break;
5916         case RENDERPATH_GL13:
5917         case RENDERPATH_GL11:
5918                 break;
5919         }
5920 }
5921
5922 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5923 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5924 /*
5925 ================
5926 R_SelectScene
5927 ================
5928 */
5929 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5930         if( scenetype != r_currentscenetype ) {
5931                 // store the old scenetype
5932                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5933                 r_currentscenetype = scenetype;
5934                 // move in the new scene
5935                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5936         }
5937 }
5938
5939 /*
5940 ================
5941 R_GetScenePointer
5942 ================
5943 */
5944 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5945 {
5946         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5947         if( scenetype == r_currentscenetype ) {
5948                 return &r_refdef.scene;
5949         } else {
5950                 return &r_scenes_store[ scenetype ];
5951         }
5952 }
5953
5954 /*
5955 ================
5956 R_RenderView
5957 ================
5958 */
5959 void R_RenderView(void)
5960 {
5961         if (r_timereport_active)
5962                 R_TimeReport("start");
5963         r_frame++; // used only by R_GetCurrentTexture
5964         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5965
5966         if (!r_drawentities.integer)
5967                 r_refdef.scene.numentities = 0;
5968
5969         R_AnimCache_ClearCache();
5970         R_FrameData_NewFrame();
5971
5972         if (r_refdef.view.isoverlay)
5973         {
5974                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5975                 GL_Clear( GL_DEPTH_BUFFER_BIT );
5976                 R_TimeReport("depthclear");
5977
5978                 r_refdef.view.showdebug = false;
5979
5980                 r_waterstate.enabled = false;
5981                 r_waterstate.numwaterplanes = 0;
5982
5983                 R_RenderScene();
5984
5985                 CHECKGLERROR
5986                 return;
5987         }
5988
5989         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
5990                 return; //Host_Error ("R_RenderView: NULL worldmodel");
5991
5992         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
5993
5994         // break apart the view matrix into vectors for various purposes
5995         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5996         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5997         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5998         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5999         // make an inverted copy of the view matrix for tracking sprites
6000         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
6001
6002         R_Shadow_UpdateWorldLightSelection();
6003
6004         R_Bloom_StartFrame();
6005         R_Water_StartFrame();
6006
6007         CHECKGLERROR
6008         if (r_timereport_active)
6009                 R_TimeReport("viewsetup");
6010
6011         R_ResetViewRendering3D();
6012
6013         if (r_refdef.view.clear || r_refdef.fogenabled)
6014         {
6015                 R_ClearScreen(r_refdef.fogenabled);
6016                 if (r_timereport_active)
6017                         R_TimeReport("viewclear");
6018         }
6019         r_refdef.view.clear = true;
6020
6021         // this produces a bloom texture to be used in R_BlendView() later
6022         if (r_hdr.integer && r_bloomstate.bloomwidth)
6023                 R_HDR_RenderBloomTexture();
6024
6025         r_refdef.view.showdebug = true;
6026
6027         R_View_Update();
6028         if (r_timereport_active)
6029                 R_TimeReport("visibility");
6030
6031         r_waterstate.numwaterplanes = 0;
6032         if (r_waterstate.enabled)
6033                 R_RenderWaterPlanes();
6034
6035         R_RenderScene();
6036         r_waterstate.numwaterplanes = 0;
6037
6038         R_BlendView();
6039         if (r_timereport_active)
6040                 R_TimeReport("blendview");
6041
6042         GL_Scissor(0, 0, vid.width, vid.height);
6043         GL_ScissorTest(false);
6044         CHECKGLERROR
6045 }
6046
6047 void R_RenderWaterPlanes(void)
6048 {
6049         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6050         {
6051                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6052                 if (r_timereport_active)
6053                         R_TimeReport("waterworld");
6054         }
6055
6056         // don't let sound skip if going slow
6057         if (r_refdef.scene.extraupdate)
6058                 S_ExtraUpdate ();
6059
6060         R_DrawModelsAddWaterPlanes();
6061         if (r_timereport_active)
6062                 R_TimeReport("watermodels");
6063
6064         if (r_waterstate.numwaterplanes)
6065         {
6066                 R_Water_ProcessPlanes();
6067                 if (r_timereport_active)
6068                         R_TimeReport("waterscenes");
6069         }
6070 }
6071
6072 extern void R_DrawLightningBeams (void);
6073 extern void VM_CL_AddPolygonsToMeshQueue (void);
6074 extern void R_DrawPortals (void);
6075 extern cvar_t cl_locs_show;
6076 static void R_DrawLocs(void);
6077 static void R_DrawEntityBBoxes(void);
6078 static void R_DrawModelDecals(void);
6079 extern cvar_t cl_decals_newsystem;
6080 extern qboolean r_shadow_usingdeferredprepass;
6081 void R_RenderScene(void)
6082 {
6083         r_refdef.stats.renders++;
6084
6085         R_UpdateFogColor();
6086
6087         // don't let sound skip if going slow
6088         if (r_refdef.scene.extraupdate)
6089                 S_ExtraUpdate ();
6090
6091         R_MeshQueue_BeginScene();
6092
6093         R_SkyStartFrame();
6094
6095         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);
6096
6097         if (cl.csqc_vidvars.drawworld)
6098         {
6099                 // don't let sound skip if going slow
6100                 if (r_refdef.scene.extraupdate)
6101                         S_ExtraUpdate ();
6102
6103                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6104                 {
6105                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6106                         if (r_timereport_active)
6107                                 R_TimeReport("worldsky");
6108                 }
6109
6110                 if (R_DrawBrushModelsSky() && r_timereport_active)
6111                         R_TimeReport("bmodelsky");
6112
6113                 if (skyrendermasked && skyrenderlater)
6114                 {
6115                         // we have to force off the water clipping plane while rendering sky
6116                         R_SetupView(false);
6117                         R_Sky();
6118                         R_SetupView(true);
6119                         if (r_timereport_active)
6120                                 R_TimeReport("sky");
6121                 }
6122         }
6123
6124         R_AnimCache_CacheVisibleEntities();
6125         if (r_timereport_active)
6126                 R_TimeReport("animation");
6127
6128         R_Shadow_PrepareLights();
6129         if (r_timereport_active)
6130                 R_TimeReport("preparelights");
6131
6132         if (r_shadow_usingdeferredprepass)
6133                 R_Shadow_DrawPrepass();
6134
6135         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6136         {
6137                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6138                 if (r_timereport_active)
6139                         R_TimeReport("worlddepth");
6140         }
6141         if (r_depthfirst.integer >= 2)
6142         {
6143                 R_DrawModelsDepth();
6144                 if (r_timereport_active)
6145                         R_TimeReport("modeldepth");
6146         }
6147
6148         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6149         {
6150                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6151                 if (r_timereport_active)
6152                         R_TimeReport("world");
6153         }
6154
6155         // don't let sound skip if going slow
6156         if (r_refdef.scene.extraupdate)
6157                 S_ExtraUpdate ();
6158
6159         R_DrawModels();
6160         if (r_timereport_active)
6161                 R_TimeReport("models");
6162
6163         // don't let sound skip if going slow
6164         if (r_refdef.scene.extraupdate)
6165                 S_ExtraUpdate ();
6166
6167         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6168         {
6169                 R_DrawModelShadows();
6170                 R_ResetViewRendering3D();
6171                 // don't let sound skip if going slow
6172                 if (r_refdef.scene.extraupdate)
6173                         S_ExtraUpdate ();
6174         }
6175
6176         if (!r_shadow_usingdeferredprepass)
6177         {
6178                 R_Shadow_DrawLights();
6179                 if (r_timereport_active)
6180                         R_TimeReport("rtlights");
6181         }
6182
6183         // don't let sound skip if going slow
6184         if (r_refdef.scene.extraupdate)
6185                 S_ExtraUpdate ();
6186
6187         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6188         {
6189                 R_DrawModelShadows();
6190                 R_ResetViewRendering3D();
6191                 // don't let sound skip if going slow
6192                 if (r_refdef.scene.extraupdate)
6193                         S_ExtraUpdate ();
6194         }
6195
6196         if (cl.csqc_vidvars.drawworld)
6197         {
6198                 if (cl_decals_newsystem.integer)
6199                 {
6200                         R_DrawModelDecals();
6201                         if (r_timereport_active)
6202                                 R_TimeReport("modeldecals");
6203                 }
6204                 else
6205                 {
6206                         R_DrawDecals();
6207                         if (r_timereport_active)
6208                                 R_TimeReport("decals");
6209                 }
6210
6211                 R_DrawParticles();
6212                 if (r_timereport_active)
6213                         R_TimeReport("particles");
6214
6215                 R_DrawExplosions();
6216                 if (r_timereport_active)
6217                         R_TimeReport("explosions");
6218
6219                 R_DrawLightningBeams();
6220                 if (r_timereport_active)
6221                         R_TimeReport("lightning");
6222         }
6223
6224         VM_CL_AddPolygonsToMeshQueue();
6225
6226         if (r_refdef.view.showdebug)
6227         {
6228                 if (cl_locs_show.integer)
6229                 {
6230                         R_DrawLocs();
6231                         if (r_timereport_active)
6232                                 R_TimeReport("showlocs");
6233                 }
6234
6235                 if (r_drawportals.integer)
6236                 {
6237                         R_DrawPortals();
6238                         if (r_timereport_active)
6239                                 R_TimeReport("portals");
6240                 }
6241
6242                 if (r_showbboxes.value > 0)
6243                 {
6244                         R_DrawEntityBBoxes();
6245                         if (r_timereport_active)
6246                                 R_TimeReport("bboxes");
6247                 }
6248         }
6249
6250         R_MeshQueue_RenderTransparent();
6251         if (r_timereport_active)
6252                 R_TimeReport("drawtrans");
6253
6254         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))
6255         {
6256                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6257                 if (r_timereport_active)
6258                         R_TimeReport("worlddebug");
6259                 R_DrawModelsDebug();
6260                 if (r_timereport_active)
6261                         R_TimeReport("modeldebug");
6262         }
6263
6264         if (cl.csqc_vidvars.drawworld)
6265         {
6266                 R_Shadow_DrawCoronas();
6267                 if (r_timereport_active)
6268                         R_TimeReport("coronas");
6269         }
6270
6271         // don't let sound skip if going slow
6272         if (r_refdef.scene.extraupdate)
6273                 S_ExtraUpdate ();
6274
6275         R_ResetViewRendering2D();
6276 }
6277
6278 static const unsigned short bboxelements[36] =
6279 {
6280         5, 1, 3, 5, 3, 7,
6281         6, 2, 0, 6, 0, 4,
6282         7, 3, 2, 7, 2, 6,
6283         4, 0, 1, 4, 1, 5,
6284         4, 5, 7, 4, 7, 6,
6285         1, 0, 2, 1, 2, 3,
6286 };
6287
6288 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6289 {
6290         int i;
6291         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6292
6293         RSurf_ActiveWorldEntity();
6294
6295         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6296         GL_DepthMask(false);
6297         GL_DepthRange(0, 1);
6298         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6299         R_Mesh_ResetTextureState();
6300
6301         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6302         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6303         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6304         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6305         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6306         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6307         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6308         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6309         R_FillColors(color4f, 8, cr, cg, cb, ca);
6310         if (r_refdef.fogenabled)
6311         {
6312                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6313                 {
6314                         f1 = RSurf_FogVertex(v);
6315                         f2 = 1 - f1;
6316                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6317                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6318                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6319                 }
6320         }
6321         R_Mesh_VertexPointer(vertex3f, 0, 0);
6322         R_Mesh_ColorPointer(color4f, 0, 0);
6323         R_Mesh_ResetTextureState();
6324         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6325         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
6326 }
6327
6328 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6329 {
6330         int i;
6331         float color[4];
6332         prvm_edict_t *edict;
6333         prvm_prog_t *prog_save = prog;
6334
6335         // this function draws bounding boxes of server entities
6336         if (!sv.active)
6337                 return;
6338
6339         GL_CullFace(GL_NONE);
6340         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6341
6342         prog = 0;
6343         SV_VM_Begin();
6344         for (i = 0;i < numsurfaces;i++)
6345         {
6346                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6347                 switch ((int)edict->fields.server->solid)
6348                 {
6349                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6350                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6351                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6352                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6353                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6354                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6355                 }
6356                 color[3] *= r_showbboxes.value;
6357                 color[3] = bound(0, color[3], 1);
6358                 GL_DepthTest(!r_showdisabledepthtest.integer);
6359                 GL_CullFace(r_refdef.view.cullface_front);
6360                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6361         }
6362         SV_VM_End();
6363         prog = prog_save;
6364 }
6365
6366 static void R_DrawEntityBBoxes(void)
6367 {
6368         int i;
6369         prvm_edict_t *edict;
6370         vec3_t center;
6371         prvm_prog_t *prog_save = prog;
6372
6373         // this function draws bounding boxes of server entities
6374         if (!sv.active)
6375                 return;
6376
6377         prog = 0;
6378         SV_VM_Begin();
6379         for (i = 0;i < prog->num_edicts;i++)
6380         {
6381                 edict = PRVM_EDICT_NUM(i);
6382                 if (edict->priv.server->free)
6383                         continue;
6384                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6385                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6386                         continue;
6387                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6388                         continue;
6389                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6390                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6391         }
6392         SV_VM_End();
6393         prog = prog_save;
6394 }
6395
6396 static const int nomodelelement3i[24] =
6397 {
6398         5, 2, 0,
6399         5, 1, 2,
6400         5, 0, 3,
6401         5, 3, 1,
6402         0, 2, 4,
6403         2, 1, 4,
6404         3, 0, 4,
6405         1, 3, 4
6406 };
6407
6408 static const unsigned short nomodelelement3s[24] =
6409 {
6410         5, 2, 0,
6411         5, 1, 2,
6412         5, 0, 3,
6413         5, 3, 1,
6414         0, 2, 4,
6415         2, 1, 4,
6416         3, 0, 4,
6417         1, 3, 4
6418 };
6419
6420 static const float nomodelvertex3f[6*3] =
6421 {
6422         -16,   0,   0,
6423          16,   0,   0,
6424           0, -16,   0,
6425           0,  16,   0,
6426           0,   0, -16,
6427           0,   0,  16
6428 };
6429
6430 static const float nomodelcolor4f[6*4] =
6431 {
6432         0.0f, 0.0f, 0.5f, 1.0f,
6433         0.0f, 0.0f, 0.5f, 1.0f,
6434         0.0f, 0.5f, 0.0f, 1.0f,
6435         0.0f, 0.5f, 0.0f, 1.0f,
6436         0.5f, 0.0f, 0.0f, 1.0f,
6437         0.5f, 0.0f, 0.0f, 1.0f
6438 };
6439
6440 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6441 {
6442         int i;
6443         float f1, f2, *c;
6444         float color4f[6*4];
6445
6446         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);
6447
6448         // this is only called once per entity so numsurfaces is always 1, and
6449         // surfacelist is always {0}, so this code does not handle batches
6450
6451         if (rsurface.ent_flags & RENDER_ADDITIVE)
6452         {
6453                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6454                 GL_DepthMask(false);
6455         }
6456         else if (rsurface.colormod[3] < 1)
6457         {
6458                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6459                 GL_DepthMask(false);
6460         }
6461         else
6462         {
6463                 GL_BlendFunc(GL_ONE, GL_ZERO);
6464                 GL_DepthMask(true);
6465         }
6466         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6467         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6468         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6469         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6470         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6471         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6472         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6473         R_Mesh_ColorPointer(color4f, 0, 0);
6474         for (i = 0, c = color4f;i < 6;i++, c += 4)
6475         {
6476                 c[0] *= rsurface.colormod[0];
6477                 c[1] *= rsurface.colormod[1];
6478                 c[2] *= rsurface.colormod[2];
6479                 c[3] *= rsurface.colormod[3];
6480         }
6481         if (r_refdef.fogenabled)
6482         {
6483                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6484                 {
6485                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
6486                         f2 = 1 - f1;
6487                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6488                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6489                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6490                 }
6491         }
6492         R_Mesh_ResetTextureState();
6493         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
6494 }
6495
6496 void R_DrawNoModel(entity_render_t *ent)
6497 {
6498         vec3_t org;
6499         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6500         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6501                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6502         else
6503                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6504 }
6505
6506 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6507 {
6508         vec3_t right1, right2, diff, normal;
6509
6510         VectorSubtract (org2, org1, normal);
6511
6512         // calculate 'right' vector for start
6513         VectorSubtract (r_refdef.view.origin, org1, diff);
6514         CrossProduct (normal, diff, right1);
6515         VectorNormalize (right1);
6516
6517         // calculate 'right' vector for end
6518         VectorSubtract (r_refdef.view.origin, org2, diff);
6519         CrossProduct (normal, diff, right2);
6520         VectorNormalize (right2);
6521
6522         vert[ 0] = org1[0] + width * right1[0];
6523         vert[ 1] = org1[1] + width * right1[1];
6524         vert[ 2] = org1[2] + width * right1[2];
6525         vert[ 3] = org1[0] - width * right1[0];
6526         vert[ 4] = org1[1] - width * right1[1];
6527         vert[ 5] = org1[2] - width * right1[2];
6528         vert[ 6] = org2[0] - width * right2[0];
6529         vert[ 7] = org2[1] - width * right2[1];
6530         vert[ 8] = org2[2] - width * right2[2];
6531         vert[ 9] = org2[0] + width * right2[0];
6532         vert[10] = org2[1] + width * right2[1];
6533         vert[11] = org2[2] + width * right2[2];
6534 }
6535
6536 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)
6537 {
6538         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6539         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6540         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6541         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6542         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6543         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6544         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6545         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6546         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6547         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6548         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6549         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
6550 }
6551
6552 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
6553 {
6554         int i;
6555         float *vertex3f;
6556         float v[3];
6557         VectorSet(v, x, y, z);
6558         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
6559                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
6560                         break;
6561         if (i == mesh->numvertices)
6562         {
6563                 if (mesh->numvertices < mesh->maxvertices)
6564                 {
6565                         VectorCopy(v, vertex3f);
6566                         mesh->numvertices++;
6567                 }
6568                 return mesh->numvertices;
6569         }
6570         else
6571                 return i;
6572 }
6573
6574 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
6575 {
6576         int i;
6577         int *e, element[3];
6578         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6579         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6580         e = mesh->element3i + mesh->numtriangles * 3;
6581         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
6582         {
6583                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
6584                 if (mesh->numtriangles < mesh->maxtriangles)
6585                 {
6586                         *e++ = element[0];
6587                         *e++ = element[1];
6588                         *e++ = element[2];
6589                         mesh->numtriangles++;
6590                 }
6591                 element[1] = element[2];
6592         }
6593 }
6594
6595 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
6596 {
6597         int i;
6598         int *e, element[3];
6599         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6600         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6601         e = mesh->element3i + mesh->numtriangles * 3;
6602         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
6603         {
6604                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
6605                 if (mesh->numtriangles < mesh->maxtriangles)
6606                 {
6607                         *e++ = element[0];
6608                         *e++ = element[1];
6609                         *e++ = element[2];
6610                         mesh->numtriangles++;
6611                 }
6612                 element[1] = element[2];
6613         }
6614 }
6615
6616 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
6617 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
6618 {
6619         int planenum, planenum2;
6620         int w;
6621         int tempnumpoints;
6622         mplane_t *plane, *plane2;
6623         double maxdist;
6624         double temppoints[2][256*3];
6625         // figure out how large a bounding box we need to properly compute this brush
6626         maxdist = 0;
6627         for (w = 0;w < numplanes;w++)
6628                 maxdist = max(maxdist, fabs(planes[w].dist));
6629         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
6630         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
6631         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
6632         {
6633                 w = 0;
6634                 tempnumpoints = 4;
6635                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
6636                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
6637                 {
6638                         if (planenum2 == planenum)
6639                                 continue;
6640                         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);
6641                         w = !w;
6642                 }
6643                 if (tempnumpoints < 3)
6644                         continue;
6645                 // generate elements forming a triangle fan for this polygon
6646                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
6647         }
6648 }
6649
6650 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)
6651 {
6652         texturelayer_t *layer;
6653         layer = t->currentlayers + t->currentnumlayers++;
6654         layer->type = type;
6655         layer->depthmask = depthmask;
6656         layer->blendfunc1 = blendfunc1;
6657         layer->blendfunc2 = blendfunc2;
6658         layer->texture = texture;
6659         layer->texmatrix = *matrix;
6660         layer->color[0] = r;
6661         layer->color[1] = g;
6662         layer->color[2] = b;
6663         layer->color[3] = a;
6664 }
6665
6666 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
6667 {
6668         double index, f;
6669         index = parms[2] + r_refdef.scene.time * parms[3];
6670         index -= floor(index);
6671         switch (func)
6672         {
6673         default:
6674         case Q3WAVEFUNC_NONE:
6675         case Q3WAVEFUNC_NOISE:
6676         case Q3WAVEFUNC_COUNT:
6677                 f = 0;
6678                 break;
6679         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
6680         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
6681         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
6682         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
6683         case Q3WAVEFUNC_TRIANGLE:
6684                 index *= 4;
6685                 f = index - floor(index);
6686                 if (index < 1)
6687                         f = f;
6688                 else if (index < 2)
6689                         f = 1 - f;
6690                 else if (index < 3)
6691                         f = -f;
6692                 else
6693                         f = -(1 - f);
6694                 break;
6695         }
6696         return (float)(parms[0] + parms[1] * f);
6697 }
6698
6699 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
6700 {
6701         int w, h, idx;
6702         float f;
6703         float tcmat[12];
6704         matrix4x4_t matrix, temp;
6705         switch(tcmod->tcmod)
6706         {
6707                 case Q3TCMOD_COUNT:
6708                 case Q3TCMOD_NONE:
6709                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6710                                 matrix = r_waterscrollmatrix;
6711                         else
6712                                 matrix = identitymatrix;
6713                         break;
6714                 case Q3TCMOD_ENTITYTRANSLATE:
6715                         // this is used in Q3 to allow the gamecode to control texcoord
6716                         // scrolling on the entity, which is not supported in darkplaces yet.
6717                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
6718                         break;
6719                 case Q3TCMOD_ROTATE:
6720                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
6721                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
6722                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
6723                         break;
6724                 case Q3TCMOD_SCALE:
6725                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
6726                         break;
6727                 case Q3TCMOD_SCROLL:
6728                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
6729                         break;
6730                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
6731                         w = (int) tcmod->parms[0];
6732                         h = (int) tcmod->parms[1];
6733                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
6734                         f = f - floor(f);
6735                         idx = (int) floor(f * w * h);
6736                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
6737                         break;
6738                 case Q3TCMOD_STRETCH:
6739                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
6740                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
6741                         break;
6742                 case Q3TCMOD_TRANSFORM:
6743                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
6744                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
6745                         VectorSet(tcmat +  6, 0                   , 0                , 1);
6746                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
6747                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
6748                         break;
6749                 case Q3TCMOD_TURBULENT:
6750                         // this is handled in the RSurf_PrepareVertices function
6751                         matrix = identitymatrix;
6752                         break;
6753         }
6754         temp = *texmatrix;
6755         Matrix4x4_Concat(texmatrix, &matrix, &temp);
6756 }
6757
6758 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
6759 {
6760         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
6761         char name[MAX_QPATH];
6762         skinframe_t *skinframe;
6763         unsigned char pixels[296*194];
6764         strlcpy(cache->name, skinname, sizeof(cache->name));
6765         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6766         if (developer_loading.integer)
6767                 Con_Printf("loading %s\n", name);
6768         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6769         if (!skinframe || !skinframe->base)
6770         {
6771                 unsigned char *f;
6772                 fs_offset_t filesize;
6773                 skinframe = NULL;
6774                 f = FS_LoadFile(name, tempmempool, true, &filesize);
6775                 if (f)
6776                 {
6777                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
6778                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6779                         Mem_Free(f);
6780                 }
6781         }
6782         cache->skinframe = skinframe;
6783 }
6784
6785 texture_t *R_GetCurrentTexture(texture_t *t)
6786 {
6787         int i;
6788         const entity_render_t *ent = rsurface.entity;
6789         dp_model_t *model = ent->model;
6790         q3shaderinfo_layer_tcmod_t *tcmod;
6791
6792         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
6793                 return t->currentframe;
6794         t->update_lastrenderframe = r_frame;
6795         t->update_lastrenderentity = (void *)ent;
6796
6797         // switch to an alternate material if this is a q1bsp animated material
6798         {
6799                 texture_t *texture = t;
6800                 int s = rsurface.ent_skinnum;
6801                 if ((unsigned int)s >= (unsigned int)model->numskins)
6802                         s = 0;
6803                 if (model->skinscenes)
6804                 {
6805                         if (model->skinscenes[s].framecount > 1)
6806                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6807                         else
6808                                 s = model->skinscenes[s].firstframe;
6809                 }
6810                 if (s > 0)
6811                         t = t + s * model->num_surfaces;
6812                 if (t->animated)
6813                 {
6814                         // use an alternate animation if the entity's frame is not 0,
6815                         // and only if the texture has an alternate animation
6816                         if (rsurface.ent_alttextures && t->anim_total[1])
6817                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6818                         else
6819                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6820                 }
6821                 texture->currentframe = t;
6822         }
6823
6824         // update currentskinframe to be a qw skin or animation frame
6825         if (rsurface.ent_qwskin >= 0)
6826         {
6827                 i = rsurface.ent_qwskin;
6828                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6829                 {
6830                         r_qwskincache_size = cl.maxclients;
6831                         if (r_qwskincache)
6832                                 Mem_Free(r_qwskincache);
6833                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6834                 }
6835                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6836                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6837                 t->currentskinframe = r_qwskincache[i].skinframe;
6838                 if (t->currentskinframe == NULL)
6839                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6840         }
6841         else if (t->numskinframes >= 2)
6842                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6843         if (t->backgroundnumskinframes >= 2)
6844                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6845
6846         t->currentmaterialflags = t->basematerialflags;
6847         t->currentalpha = rsurface.colormod[3];
6848         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6849                 t->currentalpha *= r_wateralpha.value;
6850         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6851                 t->currentalpha *= t->r_water_wateralpha;
6852         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6853                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6854         if (!(rsurface.ent_flags & RENDER_LIGHT))
6855                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6856         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6857         {
6858                 // pick a model lighting mode
6859                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6860                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6861                 else
6862                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6863         }
6864         if (rsurface.ent_flags & RENDER_ADDITIVE)
6865                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6866         else if (t->currentalpha < 1)
6867                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6868         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6869                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6870         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6871                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6872         if (t->backgroundnumskinframes)
6873                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6874         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6875         {
6876                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6877                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6878         }
6879         else
6880                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6881         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6882                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6883
6884         // there is no tcmod
6885         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6886         {
6887                 t->currenttexmatrix = r_waterscrollmatrix;
6888                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6889         }
6890         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6891         {
6892                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6893                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6894         }
6895
6896         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6897                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6898         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6899                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6900
6901         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6902         if (t->currentskinframe->qpixels)
6903                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6904         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6905         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
6906         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
6907         t->nmaptexture = t->currentskinframe->nmap;
6908         t->glosstexture = r_texture_black;
6909         t->glowtexture = t->currentskinframe->glow;
6910         t->fogtexture = t->currentskinframe->fog;
6911         if (t->backgroundnumskinframes)
6912         {
6913                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
6914                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
6915                 t->backgroundglosstexture = r_texture_black;
6916                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
6917         }
6918         else
6919         {
6920                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6921                 t->backgroundnmaptexture = r_texture_blanknormalmap;
6922                 t->backgroundglosstexture = r_texture_black;
6923                 t->backgroundglowtexture = NULL;
6924         }
6925         t->specularpower = r_shadow_glossexponent.value;
6926         // TODO: store reference values for these in the texture?
6927         t->specularscale = 0;
6928         if (r_shadow_gloss.integer > 0)
6929         {
6930                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6931                 {
6932                         if (r_shadow_glossintensity.value > 0)
6933                         {
6934                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6935                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6936                                 t->specularscale = r_shadow_glossintensity.value;
6937                         }
6938                 }
6939                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6940                 {
6941                         t->glosstexture = r_texture_white;
6942                         t->backgroundglosstexture = r_texture_white;
6943                         t->specularscale = r_shadow_gloss2intensity.value;
6944                         t->specularpower = r_shadow_gloss2exponent.value;
6945                 }
6946         }
6947         t->specularscale *= t->specularscalemod;
6948         t->specularpower *= t->specularpowermod;
6949
6950         // lightmaps mode looks bad with dlights using actual texturing, so turn
6951         // off the colormap and glossmap, but leave the normalmap on as it still
6952         // accurately represents the shading involved
6953         if (gl_lightmaps.integer)
6954         {
6955                 t->basetexture = r_texture_grey128;
6956                 t->pantstexture = r_texture_black;
6957                 t->shirttexture = r_texture_black;
6958                 t->nmaptexture = r_texture_blanknormalmap;
6959                 t->glosstexture = r_texture_black;
6960                 t->glowtexture = NULL;
6961                 t->fogtexture = NULL;
6962                 t->backgroundbasetexture = NULL;
6963                 t->backgroundnmaptexture = r_texture_blanknormalmap;
6964                 t->backgroundglosstexture = r_texture_black;
6965                 t->backgroundglowtexture = NULL;
6966                 t->specularscale = 0;
6967                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6968         }
6969
6970         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
6971         VectorClear(t->dlightcolor);
6972         t->currentnumlayers = 0;
6973         if (t->currentmaterialflags & MATERIALFLAG_WALL)
6974         {
6975                 int blendfunc1, blendfunc2;
6976                 qboolean depthmask;
6977                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6978                 {
6979                         blendfunc1 = GL_SRC_ALPHA;
6980                         blendfunc2 = GL_ONE;
6981                 }
6982                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6983                 {
6984                         blendfunc1 = GL_SRC_ALPHA;
6985                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6986                 }
6987                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6988                 {
6989                         blendfunc1 = t->customblendfunc[0];
6990                         blendfunc2 = t->customblendfunc[1];
6991                 }
6992                 else
6993                 {
6994                         blendfunc1 = GL_ONE;
6995                         blendfunc2 = GL_ZERO;
6996                 }
6997                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
6998                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6999                 {
7000                         // fullbright is not affected by r_refdef.lightmapintensity
7001                         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]);
7002                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7003                                 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]);
7004                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7005                                 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]);
7006                 }
7007                 else
7008                 {
7009                         vec3_t ambientcolor;
7010                         float colorscale;
7011                         // set the color tint used for lights affecting this surface
7012                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7013                         colorscale = 2;
7014                         // q3bsp has no lightmap updates, so the lightstylevalue that
7015                         // would normally be baked into the lightmap must be
7016                         // applied to the color
7017                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7018                         if (model->type == mod_brushq3)
7019                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7020                         colorscale *= r_refdef.lightmapintensity;
7021                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7022                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7023                         // basic lit geometry
7024                         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]);
7025                         // add pants/shirt if needed
7026                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7027                                 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]);
7028                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7029                                 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]);
7030                         // now add ambient passes if needed
7031                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7032                         {
7033                                 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]);
7034                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7035                                         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]);
7036                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7037                                         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]);
7038                         }
7039                 }
7040                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7041                         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]);
7042                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7043                 {
7044                         // if this is opaque use alpha blend which will darken the earlier
7045                         // passes cheaply.
7046                         //
7047                         // if this is an alpha blended material, all the earlier passes
7048                         // were darkened by fog already, so we only need to add the fog
7049                         // color ontop through the fog mask texture
7050                         //
7051                         // if this is an additive blended material, all the earlier passes
7052                         // were darkened by fog already, and we should not add fog color
7053                         // (because the background was not darkened, there is no fog color
7054                         // that was lost behind it).
7055                         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]);
7056                 }
7057         }
7058
7059         return t->currentframe;
7060 }
7061
7062 rsurfacestate_t rsurface;
7063
7064 void R_Mesh_ResizeArrays(int newvertices)
7065 {
7066         float *base;
7067         if (rsurface.array_size >= newvertices)
7068                 return;
7069         if (rsurface.array_modelvertex3f)
7070                 Mem_Free(rsurface.array_modelvertex3f);
7071         rsurface.array_size = (newvertices + 1023) & ~1023;
7072         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
7073         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
7074         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
7075         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
7076         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
7077         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
7078         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
7079         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
7080         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
7081         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
7082         rsurface.array_color4f           = base + rsurface.array_size * 27;
7083         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
7084 }
7085
7086 void RSurf_ActiveWorldEntity(void)
7087 {
7088         dp_model_t *model = r_refdef.scene.worldmodel;
7089         //if (rsurface.entity == r_refdef.scene.worldentity)
7090         //      return;
7091         rsurface.entity = r_refdef.scene.worldentity;
7092         rsurface.skeleton = NULL;
7093         rsurface.ent_skinnum = 0;
7094         rsurface.ent_qwskin = -1;
7095         rsurface.ent_shadertime = 0;
7096         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7097         if (rsurface.array_size < model->surfmesh.num_vertices)
7098                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
7099         rsurface.matrix = identitymatrix;
7100         rsurface.inversematrix = identitymatrix;
7101         rsurface.matrixscale = 1;
7102         rsurface.inversematrixscale = 1;
7103         R_EntityMatrix(&identitymatrix);
7104         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7105         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7106         rsurface.fograngerecip = r_refdef.fograngerecip;
7107         rsurface.fogheightfade = r_refdef.fogheightfade;
7108         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7109         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7110         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7111         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7112         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7113         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7114         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7115         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7116         rsurface.colormod[3] = 1;
7117         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);
7118         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7119         rsurface.frameblend[0].lerp = 1;
7120         rsurface.ent_alttextures = false;
7121         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7122         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7123         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7124         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
7125         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7126         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7127         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
7128         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7129         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7130         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
7131         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7132         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7133         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
7134         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7135         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7136         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
7137         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7138         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7139         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
7140         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7141         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7142         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
7143         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7144         rsurface.modelelement3i = model->surfmesh.data_element3i;
7145         rsurface.modelelement3s = model->surfmesh.data_element3s;
7146         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
7147         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
7148         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7149         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
7150         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
7151         rsurface.modelsurfaces = model->data_surfaces;
7152         rsurface.generatedvertex = false;
7153         rsurface.vertex3f  = rsurface.modelvertex3f;
7154         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7155         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7156         rsurface.svector3f = rsurface.modelsvector3f;
7157         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7158         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7159         rsurface.tvector3f = rsurface.modeltvector3f;
7160         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7161         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7162         rsurface.normal3f  = rsurface.modelnormal3f;
7163         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7164         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7165         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7166 }
7167
7168 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7169 {
7170         dp_model_t *model = ent->model;
7171         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7172         //      return;
7173         rsurface.entity = (entity_render_t *)ent;
7174         rsurface.skeleton = ent->skeleton;
7175         rsurface.ent_skinnum = ent->skinnum;
7176         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;
7177         rsurface.ent_shadertime = ent->shadertime;
7178         rsurface.ent_flags = ent->flags;
7179         if (rsurface.array_size < model->surfmesh.num_vertices)
7180                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
7181         rsurface.matrix = ent->matrix;
7182         rsurface.inversematrix = ent->inversematrix;
7183         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7184         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7185         R_EntityMatrix(&rsurface.matrix);
7186         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7187         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7188         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7189         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7190         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7191         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7192         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7193         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7194         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7195         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7196         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7197         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7198         rsurface.colormod[3] = ent->alpha;
7199         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7200         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7201         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7202         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7203         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7204         if (ent->model->brush.submodel && !prepass)
7205         {
7206                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7207                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7208         }
7209         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7210         {
7211                 if (ent->animcache_vertex3f && !r_framedata_failed)
7212                 {
7213                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7214                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7215                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7216                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7217                 }
7218                 else if (wanttangents)
7219                 {
7220                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7221                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
7222                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
7223                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7224                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
7225                 }
7226                 else if (wantnormals)
7227                 {
7228                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7229                         rsurface.modelsvector3f = NULL;
7230                         rsurface.modeltvector3f = NULL;
7231                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7232                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
7233                 }
7234                 else
7235                 {
7236                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7237                         rsurface.modelsvector3f = NULL;
7238                         rsurface.modeltvector3f = NULL;
7239                         rsurface.modelnormal3f = NULL;
7240                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
7241                 }
7242                 rsurface.modelvertex3f_bufferobject = 0;
7243                 rsurface.modelvertex3f_bufferoffset = 0;
7244                 rsurface.modelsvector3f_bufferobject = 0;
7245                 rsurface.modelsvector3f_bufferoffset = 0;
7246                 rsurface.modeltvector3f_bufferobject = 0;
7247                 rsurface.modeltvector3f_bufferoffset = 0;
7248                 rsurface.modelnormal3f_bufferobject = 0;
7249                 rsurface.modelnormal3f_bufferoffset = 0;
7250                 rsurface.generatedvertex = true;
7251         }
7252         else
7253         {
7254                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7255                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
7256                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7257                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7258                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
7259                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7260                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7261                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
7262                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7263                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7264                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
7265                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7266                 rsurface.generatedvertex = false;
7267         }
7268         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7269         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
7270         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7271         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7272         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
7273         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7274         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7275         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
7276         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7277         rsurface.modelelement3i = model->surfmesh.data_element3i;
7278         rsurface.modelelement3s = model->surfmesh.data_element3s;
7279         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
7280         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
7281         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7282         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
7283         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
7284         rsurface.modelsurfaces = model->data_surfaces;
7285         rsurface.vertex3f  = rsurface.modelvertex3f;
7286         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7287         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7288         rsurface.svector3f = rsurface.modelsvector3f;
7289         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7290         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7291         rsurface.tvector3f = rsurface.modeltvector3f;
7292         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7293         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7294         rsurface.normal3f  = rsurface.modelnormal3f;
7295         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7296         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7297         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7298 }
7299
7300 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)
7301 {
7302         rsurface.entity = r_refdef.scene.worldentity;
7303         rsurface.skeleton = NULL;
7304         rsurface.ent_skinnum = 0;
7305         rsurface.ent_qwskin = -1;
7306         rsurface.ent_shadertime = shadertime;
7307         rsurface.ent_flags = entflags;
7308         rsurface.modelnum_vertices = numvertices;
7309         rsurface.modelnum_triangles = numtriangles;
7310         if (rsurface.array_size < rsurface.modelnum_vertices)
7311                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
7312         rsurface.matrix = *matrix;
7313         rsurface.inversematrix = *inversematrix;
7314         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7315         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7316         R_EntityMatrix(&rsurface.matrix);
7317         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7318         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7319         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7320         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7321         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7322         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7323         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7324         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7325         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7326         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7327         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7328         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7329         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);
7330         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7331         rsurface.frameblend[0].lerp = 1;
7332         rsurface.ent_alttextures = false;
7333         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7334         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7335         if (wanttangents)
7336         {
7337                 rsurface.modelvertex3f = vertex3f;
7338                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
7339                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
7340                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
7341         }
7342         else if (wantnormals)
7343         {
7344                 rsurface.modelvertex3f = vertex3f;
7345                 rsurface.modelsvector3f = NULL;
7346                 rsurface.modeltvector3f = NULL;
7347                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
7348         }
7349         else
7350         {
7351                 rsurface.modelvertex3f = vertex3f;
7352                 rsurface.modelsvector3f = NULL;
7353                 rsurface.modeltvector3f = NULL;
7354                 rsurface.modelnormal3f = NULL;
7355         }
7356         rsurface.modelvertex3f_bufferobject = 0;
7357         rsurface.modelvertex3f_bufferoffset = 0;
7358         rsurface.modelsvector3f_bufferobject = 0;
7359         rsurface.modelsvector3f_bufferoffset = 0;
7360         rsurface.modeltvector3f_bufferobject = 0;
7361         rsurface.modeltvector3f_bufferoffset = 0;
7362         rsurface.modelnormal3f_bufferobject = 0;
7363         rsurface.modelnormal3f_bufferoffset = 0;
7364         rsurface.generatedvertex = true;
7365         rsurface.modellightmapcolor4f  = color4f;
7366         rsurface.modellightmapcolor4f_bufferobject = 0;
7367         rsurface.modellightmapcolor4f_bufferoffset = 0;
7368         rsurface.modeltexcoordtexture2f  = texcoord2f;
7369         rsurface.modeltexcoordtexture2f_bufferobject = 0;
7370         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7371         rsurface.modeltexcoordlightmap2f  = NULL;
7372         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
7373         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7374         rsurface.modelelement3i = element3i;
7375         rsurface.modelelement3s = element3s;
7376         rsurface.modelelement3i_bufferobject = 0;
7377         rsurface.modelelement3s_bufferobject = 0;
7378         rsurface.modellightmapoffsets = NULL;
7379         rsurface.modelsurfaces = NULL;
7380         rsurface.vertex3f  = rsurface.modelvertex3f;
7381         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7382         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7383         rsurface.svector3f = rsurface.modelsvector3f;
7384         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7385         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7386         rsurface.tvector3f = rsurface.modeltvector3f;
7387         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7388         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7389         rsurface.normal3f  = rsurface.modelnormal3f;
7390         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7391         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7392         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7393
7394         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
7395         {
7396                 if ((wantnormals || wanttangents) && !normal3f)
7397                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7398                 if (wanttangents && !svector3f)
7399                         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);
7400         }
7401 }
7402
7403 float RSurf_FogPoint(const float *v)
7404 {
7405         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7406         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7407         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7408         float FogHeightFade = r_refdef.fogheightfade;
7409         float fogfrac;
7410         unsigned int fogmasktableindex;
7411         if (r_refdef.fogplaneviewabove)
7412                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7413         else
7414                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7415         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7416         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7417 }
7418
7419 float RSurf_FogVertex(const float *v)
7420 {
7421         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7422         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7423         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7424         float FogHeightFade = rsurface.fogheightfade;
7425         float fogfrac;
7426         unsigned int fogmasktableindex;
7427         if (r_refdef.fogplaneviewabove)
7428                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7429         else
7430                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7431         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7432         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7433 }
7434
7435 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
7436 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
7437 {
7438         int deformindex;
7439         int texturesurfaceindex;
7440         int i, j;
7441         float amplitude;
7442         float animpos;
7443         float scale;
7444         const float *v1, *in_tc;
7445         float *out_tc;
7446         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
7447         float waveparms[4];
7448         q3shaderinfo_deform_t *deform;
7449         // 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
7450         if (rsurface.generatedvertex)
7451         {
7452                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
7453                         generatenormals = true;
7454                 for (i = 0;i < Q3MAXDEFORMS;i++)
7455                 {
7456                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
7457                         {
7458                                 generatetangents = true;
7459                                 generatenormals = true;
7460                         }
7461                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
7462                                 generatenormals = true;
7463                 }
7464                 if (generatenormals && !rsurface.modelnormal3f)
7465                 {
7466                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7467                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
7468                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
7469                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7470                 }
7471                 if (generatetangents && !rsurface.modelsvector3f)
7472                 {
7473                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
7474                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
7475                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
7476                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
7477                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
7478                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
7479                         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);
7480                 }
7481         }
7482         rsurface.vertex3f  = rsurface.modelvertex3f;
7483         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7484         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7485         rsurface.svector3f = rsurface.modelsvector3f;
7486         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7487         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7488         rsurface.tvector3f = rsurface.modeltvector3f;
7489         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7490         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7491         rsurface.normal3f  = rsurface.modelnormal3f;
7492         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7493         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7494         // if vertices are deformed (sprite flares and things in maps, possibly
7495         // water waves, bulges and other deformations), generate them into
7496         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
7497         // (may be static model data or generated data for an animated model, or
7498         //  the previous deform pass)
7499         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
7500         {
7501                 switch (deform->deform)
7502                 {
7503                 default:
7504                 case Q3DEFORM_PROJECTIONSHADOW:
7505                 case Q3DEFORM_TEXT0:
7506                 case Q3DEFORM_TEXT1:
7507                 case Q3DEFORM_TEXT2:
7508                 case Q3DEFORM_TEXT3:
7509                 case Q3DEFORM_TEXT4:
7510                 case Q3DEFORM_TEXT5:
7511                 case Q3DEFORM_TEXT6:
7512                 case Q3DEFORM_TEXT7:
7513                 case Q3DEFORM_NONE:
7514                         break;
7515                 case Q3DEFORM_AUTOSPRITE:
7516                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
7517                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
7518                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
7519                         VectorNormalize(newforward);
7520                         VectorNormalize(newright);
7521                         VectorNormalize(newup);
7522                         // make deformed versions of only the model vertices used by the specified surfaces
7523                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7524                         {
7525                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7526                                 // a single autosprite surface can contain multiple sprites...
7527                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
7528                                 {
7529                                         VectorClear(center);
7530                                         for (i = 0;i < 4;i++)
7531                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
7532                                         VectorScale(center, 0.25f, center);
7533                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
7534                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
7535                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
7536                                         for (i = 0;i < 4;i++)
7537                                         {
7538                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
7539                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
7540                                         }
7541                                 }
7542                                 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);
7543                                 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);
7544                         }
7545                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7546                         rsurface.vertex3f_bufferobject = 0;
7547                         rsurface.vertex3f_bufferoffset = 0;
7548                         rsurface.svector3f = rsurface.array_deformedsvector3f;
7549                         rsurface.svector3f_bufferobject = 0;
7550                         rsurface.svector3f_bufferoffset = 0;
7551                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
7552                         rsurface.tvector3f_bufferobject = 0;
7553                         rsurface.tvector3f_bufferoffset = 0;
7554                         rsurface.normal3f = rsurface.array_deformednormal3f;
7555                         rsurface.normal3f_bufferobject = 0;
7556                         rsurface.normal3f_bufferoffset = 0;
7557                         break;
7558                 case Q3DEFORM_AUTOSPRITE2:
7559                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
7560                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
7561                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
7562                         VectorNormalize(newforward);
7563                         VectorNormalize(newright);
7564                         VectorNormalize(newup);
7565                         // make deformed versions of only the model vertices used by the specified surfaces
7566                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7567                         {
7568                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7569                                 const float *v1, *v2;
7570                                 vec3_t start, end;
7571                                 float f, l;
7572                                 struct
7573                                 {
7574                                         float length2;
7575                                         const float *v1;
7576                                         const float *v2;
7577                                 }
7578                                 shortest[2];
7579                                 memset(shortest, 0, sizeof(shortest));
7580                                 // a single autosprite surface can contain multiple sprites...
7581                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
7582                                 {
7583                                         VectorClear(center);
7584                                         for (i = 0;i < 4;i++)
7585                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
7586                                         VectorScale(center, 0.25f, center);
7587                                         // find the two shortest edges, then use them to define the
7588                                         // axis vectors for rotating around the central axis
7589                                         for (i = 0;i < 6;i++)
7590                                         {
7591                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
7592                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
7593 #if 0
7594                                                 Debug_PolygonBegin(NULL, 0);
7595                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
7596                                                 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);
7597                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
7598                                                 Debug_PolygonEnd();
7599 #endif
7600                                                 l = VectorDistance2(v1, v2);
7601                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
7602                                                 if (v1[2] != v2[2])
7603                                                         l += (1.0f / 1024.0f);
7604                                                 if (shortest[0].length2 > l || i == 0)
7605                                                 {
7606                                                         shortest[1] = shortest[0];
7607                                                         shortest[0].length2 = l;
7608                                                         shortest[0].v1 = v1;
7609                                                         shortest[0].v2 = v2;
7610                                                 }
7611                                                 else if (shortest[1].length2 > l || i == 1)
7612                                                 {
7613                                                         shortest[1].length2 = l;
7614                                                         shortest[1].v1 = v1;
7615                                                         shortest[1].v2 = v2;
7616                                                 }
7617                                         }
7618                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
7619                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
7620 #if 0
7621                                         Debug_PolygonBegin(NULL, 0);
7622                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
7623                                         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);
7624                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
7625                                         Debug_PolygonEnd();
7626 #endif
7627                                         // this calculates the right vector from the shortest edge
7628                                         // and the up vector from the edge midpoints
7629                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
7630                                         VectorNormalize(right);
7631                                         VectorSubtract(end, start, up);
7632                                         VectorNormalize(up);
7633                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
7634                                         VectorSubtract(rsurface.localvieworigin, center, forward);
7635                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
7636                                         VectorNegate(forward, forward);
7637                                         VectorReflect(forward, 0, up, forward);
7638                                         VectorNormalize(forward);
7639                                         CrossProduct(up, forward, newright);
7640                                         VectorNormalize(newright);
7641 #if 0
7642                                         Debug_PolygonBegin(NULL, 0);
7643                                         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);
7644                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
7645                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
7646                                         Debug_PolygonEnd();
7647 #endif
7648 #if 0
7649                                         Debug_PolygonBegin(NULL, 0);
7650                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
7651                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
7652                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
7653                                         Debug_PolygonEnd();
7654 #endif
7655                                         // rotate the quad around the up axis vector, this is made
7656                                         // especially easy by the fact we know the quad is flat,
7657                                         // so we only have to subtract the center position and
7658                                         // measure distance along the right vector, and then
7659                                         // multiply that by the newright vector and add back the
7660                                         // center position
7661                                         // we also need to subtract the old position to undo the
7662                                         // displacement from the center, which we do with a
7663                                         // DotProduct, the subtraction/addition of center is also
7664                                         // optimized into DotProducts here
7665                                         l = DotProduct(right, center);
7666                                         for (i = 0;i < 4;i++)
7667                                         {
7668                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
7669                                                 f = DotProduct(right, v1) - l;
7670                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
7671                                         }
7672                                 }
7673                                 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);
7674                                 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);
7675                         }
7676                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7677                         rsurface.vertex3f_bufferobject = 0;
7678                         rsurface.vertex3f_bufferoffset = 0;
7679                         rsurface.svector3f = rsurface.array_deformedsvector3f;
7680                         rsurface.svector3f_bufferobject = 0;
7681                         rsurface.svector3f_bufferoffset = 0;
7682                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
7683                         rsurface.tvector3f_bufferobject = 0;
7684                         rsurface.tvector3f_bufferoffset = 0;
7685                         rsurface.normal3f = rsurface.array_deformednormal3f;
7686                         rsurface.normal3f_bufferobject = 0;
7687                         rsurface.normal3f_bufferoffset = 0;
7688                         break;
7689                 case Q3DEFORM_NORMAL:
7690                         // deform the normals to make reflections wavey
7691                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7692                         {
7693                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7694                                 for (j = 0;j < surface->num_vertices;j++)
7695                                 {
7696                                         float vertex[3];
7697                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
7698                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
7699                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
7700                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7701                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7702                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7703                                         VectorNormalize(normal);
7704                                 }
7705                                 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);
7706                         }
7707                         rsurface.svector3f = rsurface.array_deformedsvector3f;
7708                         rsurface.svector3f_bufferobject = 0;
7709                         rsurface.svector3f_bufferoffset = 0;
7710                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
7711                         rsurface.tvector3f_bufferobject = 0;
7712                         rsurface.tvector3f_bufferoffset = 0;
7713                         rsurface.normal3f = rsurface.array_deformednormal3f;
7714                         rsurface.normal3f_bufferobject = 0;
7715                         rsurface.normal3f_bufferoffset = 0;
7716                         break;
7717                 case Q3DEFORM_WAVE:
7718                         // deform vertex array to make wavey water and flags and such
7719                         waveparms[0] = deform->waveparms[0];
7720                         waveparms[1] = deform->waveparms[1];
7721                         waveparms[2] = deform->waveparms[2];
7722                         waveparms[3] = deform->waveparms[3];
7723                         // this is how a divisor of vertex influence on deformation
7724                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
7725                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
7726                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7727                         {
7728                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7729                                 for (j = 0;j < surface->num_vertices;j++)
7730                                 {
7731                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
7732                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
7733                                         // if the wavefunc depends on time, evaluate it per-vertex
7734                                         if (waveparms[3])
7735                                         {
7736                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
7737                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
7738                                         }
7739                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
7740                                 }
7741                         }
7742                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7743                         rsurface.vertex3f_bufferobject = 0;
7744                         rsurface.vertex3f_bufferoffset = 0;
7745                         break;
7746                 case Q3DEFORM_BULGE:
7747                         // deform vertex array to make the surface have moving bulges
7748                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7749                         {
7750                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7751                                 for (j = 0;j < surface->num_vertices;j++)
7752                                 {
7753                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
7754                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
7755                                 }
7756                         }
7757                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7758                         rsurface.vertex3f_bufferobject = 0;
7759                         rsurface.vertex3f_bufferoffset = 0;
7760                         break;
7761                 case Q3DEFORM_MOVE:
7762                         // deform vertex array
7763                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
7764                         VectorScale(deform->parms, scale, waveparms);
7765                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7766                         {
7767                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7768                                 for (j = 0;j < surface->num_vertices;j++)
7769                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
7770                         }
7771                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
7772                         rsurface.vertex3f_bufferobject = 0;
7773                         rsurface.vertex3f_bufferoffset = 0;
7774                         break;
7775                 }
7776         }
7777         // generate texcoords based on the chosen texcoord source
7778         switch(rsurface.texture->tcgen.tcgen)
7779         {
7780         default:
7781         case Q3TCGEN_TEXTURE:
7782                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
7783                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
7784                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
7785                 break;
7786         case Q3TCGEN_LIGHTMAP:
7787                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
7788                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
7789                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
7790                 break;
7791         case Q3TCGEN_VECTOR:
7792                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7793                 {
7794                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7795                         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)
7796                         {
7797                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
7798                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
7799                         }
7800                 }
7801                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7802                 rsurface.texcoordtexture2f_bufferobject  = 0;
7803                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7804                 break;
7805         case Q3TCGEN_ENVIRONMENT:
7806                 // make environment reflections using a spheremap
7807                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7808                 {
7809                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7810                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
7811                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
7812                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
7813                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
7814                         {
7815                                 // identical to Q3A's method, but executed in worldspace so
7816                                 // carried models can be shiny too
7817
7818                                 float viewer[3], d, reflected[3], worldreflected[3];
7819
7820                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
7821                                 // VectorNormalize(viewer);
7822
7823                                 d = DotProduct(normal, viewer);
7824
7825                                 reflected[0] = normal[0]*2*d - viewer[0];
7826                                 reflected[1] = normal[1]*2*d - viewer[1];
7827                                 reflected[2] = normal[2]*2*d - viewer[2];
7828                                 // note: this is proportinal to viewer, so we can normalize later
7829
7830                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7831                                 VectorNormalize(worldreflected);
7832
7833                                 // note: this sphere map only uses world x and z!
7834                                 // so positive and negative y will LOOK THE SAME.
7835                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7836                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7837                         }
7838                 }
7839                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7840                 rsurface.texcoordtexture2f_bufferobject  = 0;
7841                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7842                 break;
7843         }
7844         // the only tcmod that needs software vertex processing is turbulent, so
7845         // check for it here and apply the changes if needed
7846         // and we only support that as the first one
7847         // (handling a mixture of turbulent and other tcmods would be problematic
7848         //  without punting it entirely to a software path)
7849         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7850         {
7851                 amplitude = rsurface.texture->tcmods[0].parms[1];
7852                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7853                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7854                 {
7855                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7856                         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)
7857                         {
7858                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7859                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7860                         }
7861                 }
7862                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7863                 rsurface.texcoordtexture2f_bufferobject  = 0;
7864                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7865         }
7866         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
7867         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7868         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7869         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7870 }
7871
7872 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7873 {
7874         int i, j;
7875         const msurface_t *surface = texturesurfacelist[0];
7876         const msurface_t *surface2;
7877         int firstvertex;
7878         int endvertex;
7879         int numvertices;
7880         int numtriangles;
7881         // TODO: lock all array ranges before render, rather than on each surface
7882         if (texturenumsurfaces == 1)
7883         {
7884                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7885                 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);
7886         }
7887         else if (r_batchmode.integer == 2)
7888         {
7889                 #define MAXBATCHTRIANGLES 4096
7890                 int batchtriangles = 0;
7891                 static int batchelements[MAXBATCHTRIANGLES*3];
7892                 for (i = 0;i < texturenumsurfaces;i = j)
7893                 {
7894                         surface = texturesurfacelist[i];
7895                         j = i + 1;
7896                         if (surface->num_triangles > MAXBATCHTRIANGLES)
7897                         {
7898                                 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);
7899                                 continue;
7900                         }
7901                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7902                         batchtriangles = surface->num_triangles;
7903                         firstvertex = surface->num_firstvertex;
7904                         endvertex = surface->num_firstvertex + surface->num_vertices;
7905                         for (;j < texturenumsurfaces;j++)
7906                         {
7907                                 surface2 = texturesurfacelist[j];
7908                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7909                                         break;
7910                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7911                                 batchtriangles += surface2->num_triangles;
7912                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
7913                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7914                         }
7915                         surface2 = texturesurfacelist[j-1];
7916                         numvertices = endvertex - firstvertex;
7917                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7918                 }
7919         }
7920         else if (r_batchmode.integer == 1)
7921         {
7922                 for (i = 0;i < texturenumsurfaces;i = j)
7923                 {
7924                         surface = texturesurfacelist[i];
7925                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7926                                 if (texturesurfacelist[j] != surface2)
7927                                         break;
7928                         surface2 = texturesurfacelist[j-1];
7929                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7930                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7931                         GL_LockArrays(surface->num_firstvertex, numvertices);
7932                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7933                 }
7934         }
7935         else
7936         {
7937                 for (i = 0;i < texturenumsurfaces;i++)
7938                 {
7939                         surface = texturesurfacelist[i];
7940                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7941                         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);
7942                 }
7943         }
7944 }
7945
7946 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
7947 {
7948         switch(vid.renderpath)
7949         {
7950         case RENDERPATH_CGGL:
7951 #ifdef SUPPORTCG
7952                 if (r_cg_permutation->fp_Texture_Lightmap ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Lightmap , R_GetTexture(surface->lightmaptexture ));
7953                 if (r_cg_permutation->fp_Texture_Deluxemap) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Deluxemap, R_GetTexture(surface->deluxemaptexture));
7954 #endif
7955                 break;
7956         case RENDERPATH_GL20:
7957                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(surface->lightmaptexture ));
7958                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, R_GetTexture(surface->deluxemaptexture));
7959                 break;
7960         case RENDERPATH_GL13:
7961         case RENDERPATH_GL11:
7962                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
7963                 break;
7964         }
7965 }
7966
7967 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
7968 {
7969         // pick the closest matching water plane and bind textures
7970         int planeindex, vertexindex;
7971         float d, bestd;
7972         vec3_t vert;
7973         const float *v;
7974         r_waterstate_waterplane_t *p, *bestp;
7975         bestd = 0;
7976         bestp = NULL;
7977         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7978         {
7979                 d = 0;
7980                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7981                 {
7982                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
7983                         d += fabs(PlaneDiff(vert, &p->plane));
7984                 }
7985                 if (bestd > d || !bestp)
7986                 {
7987                         bestd = d;
7988                         bestp = p;
7989                 }
7990         }
7991         switch(vid.renderpath)
7992         {
7993         case RENDERPATH_CGGL:
7994 #ifdef SUPPORTCG
7995                 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));
7996                 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));
7997 #endif
7998                 break;
7999         case RENDERPATH_GL20:
8000                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));
8001                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));
8002                 break;
8003         case RENDERPATH_GL13:
8004         case RENDERPATH_GL11:
8005                 break;
8006         }
8007 }
8008
8009 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8010 {
8011         int i;
8012         const msurface_t *surface;
8013         if (r_waterstate.renderingscene)
8014                 return;
8015         for (i = 0;i < texturenumsurfaces;i++)
8016         {
8017                 surface = texturesurfacelist[i];
8018                 RSurf_BindLightmapForSurface(surface);
8019                 RSurf_BindReflectionForSurface(surface);
8020                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8021                 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);
8022         }
8023 }
8024
8025 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8026 {
8027         int i;
8028         int j;
8029         const msurface_t *surface = texturesurfacelist[0];
8030         const msurface_t *surface2;
8031         int firstvertex;
8032         int endvertex;
8033         int numvertices;
8034         int numtriangles;
8035         if (texturenumsurfaces == 1)
8036         {
8037                 RSurf_BindLightmapForSurface(surface);
8038                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8039                 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);
8040         }
8041         else if (r_batchmode.integer == 2)
8042         {
8043 #define MAXBATCHTRIANGLES 4096
8044                 int batchtriangles = 0;
8045                 static int batchelements[MAXBATCHTRIANGLES*3];
8046                 for (i = 0;i < texturenumsurfaces;i = j)
8047                 {
8048                         surface = texturesurfacelist[i];
8049                         RSurf_BindLightmapForSurface(surface);
8050                         j = i + 1;
8051                         if (surface->num_triangles > MAXBATCHTRIANGLES)
8052                         {
8053                                 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);
8054                                 continue;
8055                         }
8056                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
8057                         batchtriangles = surface->num_triangles;
8058                         firstvertex = surface->num_firstvertex;
8059                         endvertex = surface->num_firstvertex + surface->num_vertices;
8060                         for (;j < texturenumsurfaces;j++)
8061                         {
8062                                 surface2 = texturesurfacelist[j];
8063                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
8064                                         break;
8065                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
8066                                 batchtriangles += surface2->num_triangles;
8067                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
8068                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
8069                         }
8070                         surface2 = texturesurfacelist[j-1];
8071                         numvertices = endvertex - firstvertex;
8072                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
8073                 }
8074         }
8075         else if (r_batchmode.integer == 1)
8076         {
8077 #if 0
8078                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
8079                 for (i = 0;i < texturenumsurfaces;i = j)
8080                 {
8081                         surface = texturesurfacelist[i];
8082                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
8083                                 if (texturesurfacelist[j] != surface2)
8084                                         break;
8085                         Con_Printf(" %i", j - i);
8086                 }
8087                 Con_Printf("\n");
8088                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
8089 #endif
8090                 for (i = 0;i < texturenumsurfaces;i = j)
8091                 {
8092                         surface = texturesurfacelist[i];
8093                         RSurf_BindLightmapForSurface(surface);
8094                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
8095                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
8096                                         break;
8097 #if 0
8098                         Con_Printf(" %i", j - i);
8099 #endif
8100                         surface2 = texturesurfacelist[j-1];
8101                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
8102                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
8103                         GL_LockArrays(surface->num_firstvertex, numvertices);
8104                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
8105                 }
8106 #if 0
8107                 Con_Printf("\n");
8108 #endif
8109         }
8110         else
8111         {
8112                 for (i = 0;i < texturenumsurfaces;i++)
8113                 {
8114                         surface = texturesurfacelist[i];
8115                         RSurf_BindLightmapForSurface(surface);
8116                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8117                         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);
8118                 }
8119         }
8120 }
8121
8122 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8123 {
8124         int j;
8125         int texturesurfaceindex;
8126         if (r_showsurfaces.integer == 2)
8127         {
8128                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8129                 {
8130                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8131                         for (j = 0;j < surface->num_triangles;j++)
8132                         {
8133                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
8134                                 GL_Color(f, f, f, 1);
8135                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
8136                         }
8137                 }
8138         }
8139         else
8140         {
8141                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8142                 {
8143                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8144                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
8145                         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);
8146                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8147                         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);
8148                 }
8149         }
8150 }
8151
8152 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8153 {
8154         int texturesurfaceindex;
8155         int i;
8156         const float *v;
8157         float *c2;
8158         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8159         {
8160                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8161                 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)
8162                 {
8163                         c2[0] = 0.5;
8164                         c2[1] = 0.5;
8165                         c2[2] = 0.5;
8166                         c2[3] = 1;
8167                 }
8168         }
8169         rsurface.lightmapcolor4f = rsurface.array_color4f;
8170         rsurface.lightmapcolor4f_bufferobject = 0;
8171         rsurface.lightmapcolor4f_bufferoffset = 0;
8172 }
8173
8174 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8175 {
8176         int texturesurfaceindex;
8177         int i;
8178         float f;
8179         const float *v;
8180         const float *c;
8181         float *c2;
8182         if (rsurface.lightmapcolor4f)
8183         {
8184                 // generate color arrays for the surfaces in this list
8185                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8186                 {
8187                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8188                         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)
8189                         {
8190                                 f = RSurf_FogVertex(v);
8191                                 c2[0] = c[0] * f;
8192                                 c2[1] = c[1] * f;
8193                                 c2[2] = c[2] * f;
8194                                 c2[3] = c[3];
8195                         }
8196                 }
8197         }
8198         else
8199         {
8200                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8201                 {
8202                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8203                         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)
8204                         {
8205                                 f = RSurf_FogVertex(v);
8206                                 c2[0] = f;
8207                                 c2[1] = f;
8208                                 c2[2] = f;
8209                                 c2[3] = 1;
8210                         }
8211                 }
8212         }
8213         rsurface.lightmapcolor4f = rsurface.array_color4f;
8214         rsurface.lightmapcolor4f_bufferobject = 0;
8215         rsurface.lightmapcolor4f_bufferoffset = 0;
8216 }
8217
8218 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8219 {
8220         int texturesurfaceindex;
8221         int i;
8222         float f;
8223         const float *v;
8224         const float *c;
8225         float *c2;
8226         if (!rsurface.lightmapcolor4f)
8227                 return;
8228         // generate color arrays for the surfaces in this list
8229         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8230         {
8231                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8232                 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)
8233                 {
8234                         f = RSurf_FogVertex(v);
8235                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8236                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8237                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8238                         c2[3] = c[3];
8239                 }
8240         }
8241         rsurface.lightmapcolor4f = rsurface.array_color4f;
8242         rsurface.lightmapcolor4f_bufferobject = 0;
8243         rsurface.lightmapcolor4f_bufferoffset = 0;
8244 }
8245
8246 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
8247 {
8248         int texturesurfaceindex;
8249         int i;
8250         const float *c;
8251         float *c2;
8252         if (!rsurface.lightmapcolor4f)
8253                 return;
8254         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8255         {
8256                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8257                 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)
8258                 {
8259                         c2[0] = c[0] * r;
8260                         c2[1] = c[1] * g;
8261                         c2[2] = c[2] * b;
8262                         c2[3] = c[3] * a;
8263                 }
8264         }
8265         rsurface.lightmapcolor4f = rsurface.array_color4f;
8266         rsurface.lightmapcolor4f_bufferobject = 0;
8267         rsurface.lightmapcolor4f_bufferoffset = 0;
8268 }
8269
8270 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8271 {
8272         int texturesurfaceindex;
8273         int i;
8274         const float *c;
8275         float *c2;
8276         if (!rsurface.lightmapcolor4f)
8277                 return;
8278         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8279         {
8280                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8281                 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)
8282                 {
8283                         c2[0] = c[0] + r_refdef.scene.ambient;
8284                         c2[1] = c[1] + r_refdef.scene.ambient;
8285                         c2[2] = c[2] + r_refdef.scene.ambient;
8286                         c2[3] = c[3];
8287                 }
8288         }
8289         rsurface.lightmapcolor4f = rsurface.array_color4f;
8290         rsurface.lightmapcolor4f_bufferobject = 0;
8291         rsurface.lightmapcolor4f_bufferoffset = 0;
8292 }
8293
8294 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8295 {
8296         // TODO: optimize
8297         rsurface.lightmapcolor4f = NULL;
8298         rsurface.lightmapcolor4f_bufferobject = 0;
8299         rsurface.lightmapcolor4f_bufferoffset = 0;
8300         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8301         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8302         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8303         GL_Color(r, g, b, a);
8304         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
8305 }
8306
8307 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8308 {
8309         // TODO: optimize applyfog && applycolor case
8310         // just apply fog if necessary, and tint the fog color array if necessary
8311         rsurface.lightmapcolor4f = NULL;
8312         rsurface.lightmapcolor4f_bufferobject = 0;
8313         rsurface.lightmapcolor4f_bufferoffset = 0;
8314         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8315         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8316         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8317         GL_Color(r, g, b, a);
8318         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8319 }
8320
8321 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8322 {
8323         int texturesurfaceindex;
8324         int i;
8325         float *c;
8326         // TODO: optimize
8327         if (texturesurfacelist[0]->lightmapinfo)
8328         {
8329                 // generate color arrays for the surfaces in this list
8330                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8331                 {
8332                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8333                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
8334                         {
8335                                 if (surface->lightmapinfo->samples)
8336                                 {
8337                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
8338                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
8339                                         VectorScale(lm, scale, c);
8340                                         if (surface->lightmapinfo->styles[1] != 255)
8341                                         {
8342                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8343                                                 lm += size3;
8344                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
8345                                                 VectorMA(c, scale, lm, c);
8346                                                 if (surface->lightmapinfo->styles[2] != 255)
8347                                                 {
8348                                                         lm += size3;
8349                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
8350                                                         VectorMA(c, scale, lm, c);
8351                                                         if (surface->lightmapinfo->styles[3] != 255)
8352                                                         {
8353                                                                 lm += size3;
8354                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
8355                                                                 VectorMA(c, scale, lm, c);
8356                                                         }
8357                                                 }
8358                                         }
8359                                 }
8360                                 else
8361                                         VectorClear(c);
8362                                 c[3] = 1;
8363                         }
8364                 }
8365                 rsurface.lightmapcolor4f = rsurface.array_color4f;
8366                 rsurface.lightmapcolor4f_bufferobject = 0;
8367                 rsurface.lightmapcolor4f_bufferoffset = 0;
8368         }
8369         else
8370         {
8371                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8372                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8373                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8374         }
8375         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8376         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8377         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8378         GL_Color(r, g, b, a);
8379         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8380 }
8381
8382 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
8383 {
8384         int texturesurfaceindex;
8385         int i;
8386         float f;
8387         float alpha;
8388         const float *v;
8389         const float *n;
8390         float *c;
8391         vec3_t ambientcolor;
8392         vec3_t diffusecolor;
8393         vec3_t lightdir;
8394         // TODO: optimize
8395         // model lighting
8396         VectorCopy(rsurface.modellight_lightdir, lightdir);
8397         f = 0.5f * r_refdef.lightmapintensity;
8398         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
8399         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
8400         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
8401         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
8402         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
8403         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
8404         alpha = *a;
8405         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
8406         {
8407                 // generate color arrays for the surfaces in this list
8408                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8409                 {
8410                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8411                         int numverts = surface->num_vertices;
8412                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
8413                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
8414                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
8415                         // q3-style directional shading
8416                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
8417                         {
8418                                 if ((f = DotProduct(n, lightdir)) > 0)
8419                                         VectorMA(ambientcolor, f, diffusecolor, c);
8420                                 else
8421                                         VectorCopy(ambientcolor, c);
8422                                 c[3] = alpha;
8423                         }
8424                 }
8425                 *r = 1;
8426                 *g = 1;
8427                 *b = 1;
8428                 *a = 1;
8429                 rsurface.lightmapcolor4f = rsurface.array_color4f;
8430                 rsurface.lightmapcolor4f_bufferobject = 0;
8431                 rsurface.lightmapcolor4f_bufferoffset = 0;
8432                 *applycolor = false;
8433         }
8434         else
8435         {
8436                 *r = ambientcolor[0];
8437                 *g = ambientcolor[1];
8438                 *b = ambientcolor[2];
8439                 rsurface.lightmapcolor4f = NULL;
8440                 rsurface.lightmapcolor4f_bufferobject = 0;
8441                 rsurface.lightmapcolor4f_bufferoffset = 0;
8442         }
8443 }
8444
8445 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8446 {
8447         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
8448         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8449         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8450         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8451         GL_Color(r, g, b, a);
8452         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8453 }
8454
8455 void RSurf_SetupDepthAndCulling(void)
8456 {
8457         // submodels are biased to avoid z-fighting with world surfaces that they
8458         // may be exactly overlapping (avoids z-fighting artifacts on certain
8459         // doors and things in Quake maps)
8460         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
8461         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
8462         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
8463         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
8464 }
8465
8466 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8467 {
8468         // transparent sky would be ridiculous
8469         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8470                 return;
8471         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8472         skyrenderlater = true;
8473         RSurf_SetupDepthAndCulling();
8474         GL_DepthMask(true);
8475         // LordHavoc: HalfLife maps have freaky skypolys so don't use
8476         // skymasking on them, and Quake3 never did sky masking (unlike
8477         // software Quake and software Quake2), so disable the sky masking
8478         // in Quake3 maps as it causes problems with q3map2 sky tricks,
8479         // and skymasking also looks very bad when noclipping outside the
8480         // level, so don't use it then either.
8481         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
8482         {
8483                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
8484                 R_Mesh_ColorPointer(NULL, 0, 0);
8485                 R_Mesh_ResetTextureState();
8486                 if (skyrendermasked)
8487                 {
8488                         R_SetupShader_DepthOrShadow();
8489                         // depth-only (masking)
8490                         GL_ColorMask(0,0,0,0);
8491                         // just to make sure that braindead drivers don't draw
8492                         // anything despite that colormask...
8493                         GL_BlendFunc(GL_ZERO, GL_ONE);
8494                 }
8495                 else
8496                 {
8497                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8498                         // fog sky
8499                         GL_BlendFunc(GL_ONE, GL_ZERO);
8500                 }
8501                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8502                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8503                 if (skyrendermasked)
8504                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8505         }
8506         R_Mesh_ResetTextureState();
8507         GL_Color(1, 1, 1, 1);
8508 }
8509
8510 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
8511 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
8512 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8513 {
8514         qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
8515         qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
8516
8517         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
8518                 return;
8519
8520         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
8521                 R_Mesh_ColorPointer(NULL, 0, 0);
8522         else
8523                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
8524
8525         if (refract)
8526         {
8527                 // render background
8528                 GL_BlendFunc(GL_ONE, GL_ZERO);
8529                 GL_DepthMask(true);
8530                 GL_AlphaTest(false);
8531
8532                 GL_Color(1, 1, 1, 1);
8533                 R_Mesh_ColorPointer(NULL, 0, 0);
8534
8535                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
8536                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
8537                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8538                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
8539                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
8540                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
8541                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8542                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8543                 GL_LockArrays(0, 0);
8544
8545                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
8546                 GL_DepthMask(false);
8547                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
8548                         R_Mesh_ColorPointer(NULL, 0, 0);
8549                 else
8550                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
8551         }
8552
8553         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
8554
8555         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
8556         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8557         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
8558         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
8559         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
8560         if (!prepass)
8561                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8562
8563         if (refract)
8564         {
8565                 GL_BlendFunc(GL_ONE, GL_ZERO);
8566                 GL_DepthMask(true);
8567                 GL_AlphaTest(false);
8568         }
8569         else
8570         {
8571                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
8572                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8573                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
8574         }
8575
8576         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8577         {
8578                 if (refract || reflect)
8579                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8580                 else
8581                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
8582         }
8583         else
8584         {
8585                 if (refract || reflect)
8586                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8587                 else
8588                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8589         }
8590         GL_LockArrays(0, 0);
8591 }
8592
8593 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8594 {
8595         // OpenGL 1.3 path - anything not completely ancient
8596         int texturesurfaceindex;
8597         qboolean applycolor;
8598         qboolean applyfog;
8599         int layerindex;
8600         const texturelayer_t *layer;
8601         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8602
8603         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
8604         {
8605                 vec4_t layercolor;
8606                 int layertexrgbscale;
8607                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8608                 {
8609                         if (layerindex == 0)
8610                                 GL_AlphaTest(true);
8611                         else
8612                         {
8613                                 GL_AlphaTest(false);
8614                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
8615                         }
8616                 }
8617                 GL_DepthMask(layer->depthmask && writedepth);
8618                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
8619                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
8620                 {
8621                         layertexrgbscale = 4;
8622                         VectorScale(layer->color, 0.25f, layercolor);
8623                 }
8624                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
8625                 {
8626                         layertexrgbscale = 2;
8627                         VectorScale(layer->color, 0.5f, layercolor);
8628                 }
8629                 else
8630                 {
8631                         layertexrgbscale = 1;
8632                         VectorScale(layer->color, 1.0f, layercolor);
8633                 }
8634                 layercolor[3] = layer->color[3];
8635                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
8636                 R_Mesh_ColorPointer(NULL, 0, 0);
8637                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
8638                 switch (layer->type)
8639                 {
8640                 case TEXTURELAYERTYPE_LITTEXTURE:
8641                         // single-pass lightmapped texture with 2x rgbscale
8642                         //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8643                         R_Mesh_TexMatrix(0, NULL);
8644                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8645                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8646                         R_Mesh_TexBind(1, R_GetTexture(layer->texture));
8647                         R_Mesh_TexMatrix(1, &layer->texmatrix);
8648                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8649                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8650                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8651                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8652                         else if (rsurface.uselightmaptexture)
8653                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8654                         else
8655                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8656                         break;
8657                 case TEXTURELAYERTYPE_TEXTURE:
8658                         // singletexture unlit texture with transparency support
8659                         R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8660                         R_Mesh_TexMatrix(0, &layer->texmatrix);
8661                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8662                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8663                         R_Mesh_TexBind(1, 0);
8664                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
8665                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8666                         break;
8667                 case TEXTURELAYERTYPE_FOG:
8668                         // singletexture fogging
8669                         if (layer->texture)
8670                         {
8671                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8672                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8673                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8674                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8675                         }
8676                         else
8677                         {
8678                                 R_Mesh_TexBind(0, 0);
8679                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8680                         }
8681                         R_Mesh_TexBind(1, 0);
8682                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
8683                         // generate a color array for the fog pass
8684                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8685                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8686                         {
8687                                 int i;
8688                                 float f;
8689                                 const float *v;
8690                                 float *c;
8691                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8692                                 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)
8693                                 {
8694                                         f = 1 - RSurf_FogVertex(v);
8695                                         c[0] = layercolor[0];
8696                                         c[1] = layercolor[1];
8697                                         c[2] = layercolor[2];
8698                                         c[3] = f * layercolor[3];
8699                                 }
8700                         }
8701                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8702                         break;
8703                 default:
8704                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8705                 }
8706                 GL_LockArrays(0, 0);
8707         }
8708         CHECKGLERROR
8709         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8710         {
8711                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8712                 GL_AlphaTest(false);
8713         }
8714 }
8715
8716 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8717 {
8718         // OpenGL 1.1 - crusty old voodoo path
8719         int texturesurfaceindex;
8720         qboolean applyfog;
8721         int layerindex;
8722         const texturelayer_t *layer;
8723         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8724
8725         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
8726         {
8727                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8728                 {
8729                         if (layerindex == 0)
8730                                 GL_AlphaTest(true);
8731                         else
8732                         {
8733                                 GL_AlphaTest(false);
8734                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
8735                         }
8736                 }
8737                 GL_DepthMask(layer->depthmask && writedepth);
8738                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
8739                 R_Mesh_ColorPointer(NULL, 0, 0);
8740                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
8741                 switch (layer->type)
8742                 {
8743                 case TEXTURELAYERTYPE_LITTEXTURE:
8744                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
8745                         {
8746                                 // two-pass lit texture with 2x rgbscale
8747                                 // first the lightmap pass
8748                                 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8749                                 R_Mesh_TexMatrix(0, NULL);
8750                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8751                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8752                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8753                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8754                                 else if (rsurface.uselightmaptexture)
8755                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8756                                 else
8757                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8758                                 GL_LockArrays(0, 0);
8759                                 // then apply the texture to it
8760                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8761                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8762                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8763                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8764                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8765                                 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);
8766                         }
8767                         else
8768                         {
8769                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
8770                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8771                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8772                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8773                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8774                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8775                                         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);
8776                                 else
8777                                         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);
8778                         }
8779                         break;
8780                 case TEXTURELAYERTYPE_TEXTURE:
8781                         // singletexture unlit texture with transparency support
8782                         R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8783                         R_Mesh_TexMatrix(0, &layer->texmatrix);
8784                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8785                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8786                         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);
8787                         break;
8788                 case TEXTURELAYERTYPE_FOG:
8789                         // singletexture fogging
8790                         if (layer->texture)
8791                         {
8792                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8793                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8794                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8795                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8796                         }
8797                         else
8798                         {
8799                                 R_Mesh_TexBind(0, 0);
8800                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8801                         }
8802                         // generate a color array for the fog pass
8803                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8804                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8805                         {
8806                                 int i;
8807                                 float f;
8808                                 const float *v;
8809                                 float *c;
8810                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8811                                 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)
8812                                 {
8813                                         f = 1 - RSurf_FogVertex(v);
8814                                         c[0] = layer->color[0];
8815                                         c[1] = layer->color[1];
8816                                         c[2] = layer->color[2];
8817                                         c[3] = f * layer->color[3];
8818                                 }
8819                         }
8820                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8821                         break;
8822                 default:
8823                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8824                 }
8825                 GL_LockArrays(0, 0);
8826         }
8827         CHECKGLERROR
8828         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8829         {
8830                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8831                 GL_AlphaTest(false);
8832         }
8833 }
8834
8835 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8836 {
8837         float c[4];
8838
8839         GL_AlphaTest(false);
8840         R_Mesh_ColorPointer(NULL, 0, 0);
8841         R_Mesh_ResetTextureState();
8842         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8843
8844         if(rsurface.texture && rsurface.texture->currentskinframe)
8845         {
8846                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8847                 c[3] *= rsurface.texture->currentalpha;
8848         }
8849         else
8850         {
8851                 c[0] = 1;
8852                 c[1] = 0;
8853                 c[2] = 1;
8854                 c[3] = 1;
8855         }
8856
8857         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
8858         {
8859                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8860                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8861                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8862         }
8863
8864         // brighten it up (as texture value 127 means "unlit")
8865         c[0] *= 2 * r_refdef.view.colorscale;
8866         c[1] *= 2 * r_refdef.view.colorscale;
8867         c[2] *= 2 * r_refdef.view.colorscale;
8868
8869         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8870                 c[3] *= r_wateralpha.value;
8871
8872         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8873         {
8874                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8875                 GL_DepthMask(false);
8876         }
8877         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8878         {
8879                 GL_BlendFunc(GL_ONE, GL_ONE);
8880                 GL_DepthMask(false);
8881         }
8882         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8883         {
8884                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8885                 GL_DepthMask(false);
8886         }
8887         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8888         {
8889                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8890                 GL_DepthMask(false);
8891         }
8892         else
8893         {
8894                 GL_BlendFunc(GL_ONE, GL_ZERO);
8895                 GL_DepthMask(writedepth);
8896         }
8897
8898         rsurface.lightmapcolor4f = NULL;
8899
8900         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8901         {
8902                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8903
8904                 rsurface.lightmapcolor4f = NULL;
8905                 rsurface.lightmapcolor4f_bufferobject = 0;
8906                 rsurface.lightmapcolor4f_bufferoffset = 0;
8907         }
8908         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8909         {
8910                 qboolean applycolor = true;
8911                 float one = 1.0;
8912
8913                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8914
8915                 r_refdef.lightmapintensity = 1;
8916                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8917                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8918         }
8919         else
8920         {
8921                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8922
8923                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8924                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8925                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8926         }
8927
8928         if(!rsurface.lightmapcolor4f)
8929                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8930
8931         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8932         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8933         if(r_refdef.fogenabled)
8934                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8935
8936         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8937         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8938 }
8939
8940 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8941 {
8942         CHECKGLERROR
8943         RSurf_SetupDepthAndCulling();
8944         if (r_showsurfaces.integer == 3 && !prepass)
8945         {
8946                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8947                 return;
8948         }
8949         switch (vid.renderpath)
8950         {
8951         case RENDERPATH_GL20:
8952         case RENDERPATH_CGGL:
8953                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8954                 break;
8955         case RENDERPATH_GL13:
8956                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8957                 break;
8958         case RENDERPATH_GL11:
8959                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8960                 break;
8961         }
8962         CHECKGLERROR
8963 }
8964
8965 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8966 {
8967         CHECKGLERROR
8968         RSurf_SetupDepthAndCulling();
8969         if (r_showsurfaces.integer == 3 && !prepass)
8970         {
8971                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8972                 return;
8973         }
8974         switch (vid.renderpath)
8975         {
8976         case RENDERPATH_GL20:
8977         case RENDERPATH_CGGL:
8978                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8979                 break;
8980         case RENDERPATH_GL13:
8981                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8982                 break;
8983         case RENDERPATH_GL11:
8984                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8985                 break;
8986         }
8987         CHECKGLERROR
8988 }
8989
8990 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8991 {
8992         int i, j;
8993         int texturenumsurfaces, endsurface;
8994         texture_t *texture;
8995         const msurface_t *surface;
8996         const msurface_t *texturesurfacelist[256];
8997
8998         // if the model is static it doesn't matter what value we give for
8999         // wantnormals and wanttangents, so this logic uses only rules applicable
9000         // to a model, knowing that they are meaningless otherwise
9001         if (ent == r_refdef.scene.worldentity)
9002                 RSurf_ActiveWorldEntity();
9003         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9004                 RSurf_ActiveModelEntity(ent, false, false, false);
9005         else
9006         {
9007                 switch (vid.renderpath)
9008                 {
9009                 case RENDERPATH_GL20:
9010                 case RENDERPATH_CGGL:
9011                         RSurf_ActiveModelEntity(ent, true, true, false);
9012                         break;
9013                 case RENDERPATH_GL13:
9014                 case RENDERPATH_GL11:
9015                         RSurf_ActiveModelEntity(ent, true, false, false);
9016                         break;
9017                 }
9018         }
9019
9020         if (r_transparentdepthmasking.integer)
9021         {
9022                 qboolean setup = false;
9023                 for (i = 0;i < numsurfaces;i = j)
9024                 {
9025                         j = i + 1;
9026                         surface = rsurface.modelsurfaces + surfacelist[i];
9027                         texture = surface->texture;
9028                         rsurface.texture = R_GetCurrentTexture(texture);
9029                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9030                         // scan ahead until we find a different texture
9031                         endsurface = min(i + 1024, numsurfaces);
9032                         texturenumsurfaces = 0;
9033                         texturesurfacelist[texturenumsurfaces++] = surface;
9034                         for (;j < endsurface;j++)
9035                         {
9036                                 surface = rsurface.modelsurfaces + surfacelist[j];
9037                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
9038                                         break;
9039                                 texturesurfacelist[texturenumsurfaces++] = surface;
9040                         }
9041                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9042                                 continue;
9043                         // render the range of surfaces as depth
9044                         if (!setup)
9045                         {
9046                                 setup = true;
9047                                 GL_ColorMask(0,0,0,0);
9048                                 GL_Color(1,1,1,1);
9049                                 GL_DepthTest(true);
9050                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9051                                 GL_DepthMask(true);
9052                                 GL_AlphaTest(false);
9053                                 R_Mesh_ColorPointer(NULL, 0, 0);
9054                                 R_Mesh_ResetTextureState();
9055                                 R_SetupShader_DepthOrShadow();
9056                         }
9057                         RSurf_SetupDepthAndCulling();
9058                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9059                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9060                 }
9061                 if (setup)
9062                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9063         }
9064
9065         for (i = 0;i < numsurfaces;i = j)
9066         {
9067                 j = i + 1;
9068                 surface = rsurface.modelsurfaces + surfacelist[i];
9069                 texture = surface->texture;
9070                 rsurface.texture = R_GetCurrentTexture(texture);
9071                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9072                 // scan ahead until we find a different texture
9073                 endsurface = min(i + 1024, numsurfaces);
9074                 texturenumsurfaces = 0;
9075                 texturesurfacelist[texturenumsurfaces++] = surface;
9076                 for (;j < endsurface;j++)
9077                 {
9078                         surface = rsurface.modelsurfaces + surfacelist[j];
9079                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
9080                                 break;
9081                         texturesurfacelist[texturenumsurfaces++] = surface;
9082                 }
9083                 // render the range of surfaces
9084                 if (ent == r_refdef.scene.worldentity)
9085                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9086                 else
9087                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9088         }
9089         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9090         GL_AlphaTest(false);
9091 }
9092
9093 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9094 {
9095         // transparent surfaces get pushed off into the transparent queue
9096         int surfacelistindex;
9097         const msurface_t *surface;
9098         vec3_t tempcenter, center;
9099         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9100         {
9101                 surface = texturesurfacelist[surfacelistindex];
9102                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9103                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9104                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9105                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9106                 if (queueentity->transparent_offset) // transparent offset
9107                 {
9108                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9109                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9110                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9111                 }
9112                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9113         }
9114 }
9115
9116 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9117 {
9118         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9119         CHECKGLERROR
9120         if (depthonly)
9121         {
9122                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9123                         return;
9124                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9125                         return;
9126                 RSurf_SetupDepthAndCulling();
9127                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9128                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9129         }
9130         else if (prepass)
9131         {
9132                 if (!rsurface.texture->currentnumlayers)
9133                         return;
9134                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9135                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9136                 else
9137                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9138         }
9139         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
9140         {
9141                 RSurf_SetupDepthAndCulling();
9142                 GL_AlphaTest(false);
9143                 R_Mesh_ColorPointer(NULL, 0, 0);
9144                 R_Mesh_ResetTextureState();
9145                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9146                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9147                 GL_DepthMask(true);
9148                 GL_BlendFunc(GL_ONE, GL_ZERO);
9149                 GL_Color(0, 0, 0, 1);
9150                 GL_DepthTest(writedepth);
9151                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9152         }
9153         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
9154         {
9155                 RSurf_SetupDepthAndCulling();
9156                 GL_AlphaTest(false);
9157                 R_Mesh_ColorPointer(NULL, 0, 0);
9158                 R_Mesh_ResetTextureState();
9159                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9160                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9161                 GL_DepthMask(true);
9162                 GL_BlendFunc(GL_ONE, GL_ZERO);
9163                 GL_DepthTest(true);
9164                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
9165         }
9166         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
9167                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9168         else if (!rsurface.texture->currentnumlayers)
9169                 return;
9170         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9171         {
9172                 // in the deferred case, transparent surfaces were queued during prepass
9173                 if (!r_shadow_usingdeferredprepass)
9174                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9175         }
9176         else
9177         {
9178                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9179                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9180         }
9181         CHECKGLERROR
9182 }
9183
9184 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9185 {
9186         int i, j;
9187         texture_t *texture;
9188         // break the surface list down into batches by texture and use of lightmapping
9189         for (i = 0;i < numsurfaces;i = j)
9190         {
9191                 j = i + 1;
9192                 // texture is the base texture pointer, rsurface.texture is the
9193                 // current frame/skin the texture is directing us to use (for example
9194                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9195                 // use skin 1 instead)
9196                 texture = surfacelist[i]->texture;
9197                 rsurface.texture = R_GetCurrentTexture(texture);
9198                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
9199                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9200                 {
9201                         // if this texture is not the kind we want, skip ahead to the next one
9202                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9203                                 ;
9204                         continue;
9205                 }
9206                 // simply scan ahead until we find a different texture or lightmap state
9207                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
9208                         ;
9209                 // render the range of surfaces
9210                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
9211         }
9212 }
9213
9214 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
9215 {
9216         CHECKGLERROR
9217         if (depthonly)
9218         {
9219                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9220                         return;
9221                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9222                         return;
9223                 RSurf_SetupDepthAndCulling();
9224                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9225                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9226         }
9227         else if (prepass)
9228         {
9229                 if (!rsurface.texture->currentnumlayers)
9230                         return;
9231                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9232                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9233                 else
9234                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9235         }
9236         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
9237         {
9238                 RSurf_SetupDepthAndCulling();
9239                 GL_AlphaTest(false);
9240                 R_Mesh_ColorPointer(NULL, 0, 0);
9241                 R_Mesh_ResetTextureState();
9242                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9243                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9244                 GL_DepthMask(true);
9245                 GL_BlendFunc(GL_ONE, GL_ZERO);
9246                 GL_Color(0, 0, 0, 1);
9247                 GL_DepthTest(writedepth);
9248                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9249         }
9250         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9251         {
9252                 RSurf_SetupDepthAndCulling();
9253                 GL_AlphaTest(false);
9254                 R_Mesh_ColorPointer(NULL, 0, 0);
9255                 R_Mesh_ResetTextureState();
9256                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9257                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9258                 GL_DepthMask(true);
9259                 GL_BlendFunc(GL_ONE, GL_ZERO);
9260                 GL_DepthTest(true);
9261                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
9262         }
9263         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
9264                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9265         else if (!rsurface.texture->currentnumlayers)
9266                 return;
9267         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9268         {
9269                 // in the deferred case, transparent surfaces were queued during prepass
9270                 if (!r_shadow_usingdeferredprepass)
9271                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9272         }
9273         else
9274         {
9275                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9276                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9277         }
9278         CHECKGLERROR
9279 }
9280
9281 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9282 {
9283         int i, j;
9284         texture_t *texture;
9285         // break the surface list down into batches by texture and use of lightmapping
9286         for (i = 0;i < numsurfaces;i = j)
9287         {
9288                 j = i + 1;
9289                 // texture is the base texture pointer, rsurface.texture is the
9290                 // current frame/skin the texture is directing us to use (for example
9291                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9292                 // use skin 1 instead)
9293                 texture = surfacelist[i]->texture;
9294                 rsurface.texture = R_GetCurrentTexture(texture);
9295                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
9296                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9297                 {
9298                         // if this texture is not the kind we want, skip ahead to the next one
9299                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9300                                 ;
9301                         continue;
9302                 }
9303                 // simply scan ahead until we find a different texture or lightmap state
9304                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
9305                         ;
9306                 // render the range of surfaces
9307                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
9308         }
9309 }
9310
9311 float locboxvertex3f[6*4*3] =
9312 {
9313         1,0,1, 1,0,0, 1,1,0, 1,1,1,
9314         0,1,1, 0,1,0, 0,0,0, 0,0,1,
9315         1,1,1, 1,1,0, 0,1,0, 0,1,1,
9316         0,0,1, 0,0,0, 1,0,0, 1,0,1,
9317         0,0,1, 1,0,1, 1,1,1, 0,1,1,
9318         1,0,0, 0,0,0, 0,1,0, 1,1,0
9319 };
9320
9321 unsigned short locboxelements[6*2*3] =
9322 {
9323          0, 1, 2, 0, 2, 3,
9324          4, 5, 6, 4, 6, 7,
9325          8, 9,10, 8,10,11,
9326         12,13,14, 12,14,15,
9327         16,17,18, 16,18,19,
9328         20,21,22, 20,22,23
9329 };
9330
9331 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9332 {
9333         int i, j;
9334         cl_locnode_t *loc = (cl_locnode_t *)ent;
9335         vec3_t mins, size;
9336         float vertex3f[6*4*3];
9337         CHECKGLERROR
9338         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9339         GL_DepthMask(false);
9340         GL_DepthRange(0, 1);
9341         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9342         GL_DepthTest(true);
9343         GL_CullFace(GL_NONE);
9344         R_EntityMatrix(&identitymatrix);
9345
9346         R_Mesh_VertexPointer(vertex3f, 0, 0);
9347         R_Mesh_ColorPointer(NULL, 0, 0);
9348         R_Mesh_ResetTextureState();
9349         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9350
9351         i = surfacelist[0];
9352         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9353                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9354                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9355                         surfacelist[0] < 0 ? 0.5f : 0.125f);
9356
9357         if (VectorCompare(loc->mins, loc->maxs))
9358         {
9359                 VectorSet(size, 2, 2, 2);
9360                 VectorMA(loc->mins, -0.5f, size, mins);
9361         }
9362         else
9363         {
9364                 VectorCopy(loc->mins, mins);
9365                 VectorSubtract(loc->maxs, loc->mins, size);
9366         }
9367
9368         for (i = 0;i < 6*4*3;)
9369                 for (j = 0;j < 3;j++, i++)
9370                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
9371
9372         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
9373 }
9374
9375 void R_DrawLocs(void)
9376 {
9377         int index;
9378         cl_locnode_t *loc, *nearestloc;
9379         vec3_t center;
9380         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
9381         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
9382         {
9383                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
9384                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
9385         }
9386 }
9387
9388 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
9389 {
9390         if (decalsystem->decals)
9391                 Mem_Free(decalsystem->decals);
9392         memset(decalsystem, 0, sizeof(*decalsystem));
9393 }
9394
9395 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)
9396 {
9397         tridecal_t *decal;
9398         tridecal_t *decals;
9399         int i;
9400         int maxdecals;
9401
9402         // expand or initialize the system
9403         if (decalsystem->maxdecals <= decalsystem->numdecals)
9404         {
9405                 decalsystem_t old = *decalsystem;
9406                 qboolean useshortelements;
9407                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
9408                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
9409                 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)));
9410                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
9411                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
9412                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
9413                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
9414                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
9415                 if (decalsystem->numdecals)
9416                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
9417                 if (old.decals)
9418                         Mem_Free(old.decals);
9419                 for (i = 0;i < decalsystem->maxdecals*3;i++)
9420                         decalsystem->element3i[i] = i;
9421                 if (useshortelements)
9422                         for (i = 0;i < decalsystem->maxdecals*3;i++)
9423                                 decalsystem->element3s[i] = i;
9424         }
9425
9426         // grab a decal and search for another free slot for the next one
9427         maxdecals = decalsystem->maxdecals;
9428         decals = decalsystem->decals;
9429         decal = decalsystem->decals + (i = decalsystem->freedecal++);
9430         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
9431                 ;
9432         decalsystem->freedecal = i;
9433         if (decalsystem->numdecals <= i)
9434                 decalsystem->numdecals = i + 1;
9435
9436         // initialize the decal
9437         decal->lived = 0;
9438         decal->triangleindex = triangleindex;
9439         decal->surfaceindex = surfaceindex;
9440         decal->decalsequence = decalsequence;
9441         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
9442         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
9443         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
9444         decal->color4ub[0][3] = 255;
9445         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
9446         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
9447         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
9448         decal->color4ub[1][3] = 255;
9449         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
9450         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
9451         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
9452         decal->color4ub[2][3] = 255;
9453         decal->vertex3f[0][0] = v0[0];
9454         decal->vertex3f[0][1] = v0[1];
9455         decal->vertex3f[0][2] = v0[2];
9456         decal->vertex3f[1][0] = v1[0];
9457         decal->vertex3f[1][1] = v1[1];
9458         decal->vertex3f[1][2] = v1[2];
9459         decal->vertex3f[2][0] = v2[0];
9460         decal->vertex3f[2][1] = v2[1];
9461         decal->vertex3f[2][2] = v2[2];
9462         decal->texcoord2f[0][0] = t0[0];
9463         decal->texcoord2f[0][1] = t0[1];
9464         decal->texcoord2f[1][0] = t1[0];
9465         decal->texcoord2f[1][1] = t1[1];
9466         decal->texcoord2f[2][0] = t2[0];
9467         decal->texcoord2f[2][1] = t2[1];
9468 }
9469
9470 extern cvar_t cl_decals_bias;
9471 extern cvar_t cl_decals_models;
9472 extern cvar_t cl_decals_newsystem_intensitymultiplier;
9473 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)
9474 {
9475         matrix4x4_t projection;
9476         decalsystem_t *decalsystem;
9477         qboolean dynamic;
9478         dp_model_t *model;
9479         const float *vertex3f;
9480         const msurface_t *surface;
9481         const msurface_t *surfaces;
9482         const int *surfacelist;
9483         const texture_t *texture;
9484         int numvertices;
9485         int numtriangles;
9486         int numsurfacelist;
9487         int surfacelistindex;
9488         int surfaceindex;
9489         int triangleindex;
9490         int decalsurfaceindex;
9491         int cornerindex;
9492         int index;
9493         int numpoints;
9494         const int *e;
9495         float localorigin[3];
9496         float localnormal[3];
9497         float localmins[3];
9498         float localmaxs[3];
9499         float localsize;
9500         float ilocalsize;
9501         float v[9][3];
9502         float tc[9][2];
9503         float c[9][4];
9504         //float normal[3];
9505         float planes[6][4];
9506         float f;
9507         float points[2][9][3];
9508         float angles[3];
9509         float temp[3];
9510
9511         decalsystem = &ent->decalsystem;
9512         model = ent->model;
9513         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
9514         {
9515                 R_DecalSystem_Reset(&ent->decalsystem);
9516                 return;
9517         }
9518
9519         if (!model->brush.data_nodes && !cl_decals_models.integer)
9520         {
9521                 if (decalsystem->model)
9522                         R_DecalSystem_Reset(decalsystem);
9523                 return;
9524         }
9525
9526         if (decalsystem->model != model)
9527                 R_DecalSystem_Reset(decalsystem);
9528         decalsystem->model = model;
9529
9530         RSurf_ActiveModelEntity(ent, false, false, false);
9531
9532         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
9533         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
9534         VectorNormalize(localnormal);
9535         localsize = worldsize*rsurface.inversematrixscale;
9536         ilocalsize = 1.0f / localsize;
9537         localmins[0] = localorigin[0] - localsize;
9538         localmins[1] = localorigin[1] - localsize;
9539         localmins[2] = localorigin[2] - localsize;
9540         localmaxs[0] = localorigin[0] + localsize;
9541         localmaxs[1] = localorigin[1] + localsize;
9542         localmaxs[2] = localorigin[2] + localsize;
9543
9544         //VectorCopy(localnormal, planes[4]);
9545         //VectorVectors(planes[4], planes[2], planes[0]);
9546         AnglesFromVectors(angles, localnormal, NULL, false);
9547         AngleVectors(angles, planes[0], planes[2], planes[4]);
9548         VectorNegate(planes[0], planes[1]);
9549         VectorNegate(planes[2], planes[3]);
9550         VectorNegate(planes[4], planes[5]);
9551         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
9552         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
9553         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
9554         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
9555         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
9556         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
9557
9558 #if 1
9559 // works
9560 {
9561         matrix4x4_t forwardprojection;
9562         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
9563         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
9564 }
9565 #else
9566 // broken
9567 {
9568         float projectionvector[4][3];
9569         VectorScale(planes[0], ilocalsize, projectionvector[0]);
9570         VectorScale(planes[2], ilocalsize, projectionvector[1]);
9571         VectorScale(planes[4], ilocalsize, projectionvector[2]);
9572         projectionvector[0][0] = planes[0][0] * ilocalsize;
9573         projectionvector[0][1] = planes[1][0] * ilocalsize;
9574         projectionvector[0][2] = planes[2][0] * ilocalsize;
9575         projectionvector[1][0] = planes[0][1] * ilocalsize;
9576         projectionvector[1][1] = planes[1][1] * ilocalsize;
9577         projectionvector[1][2] = planes[2][1] * ilocalsize;
9578         projectionvector[2][0] = planes[0][2] * ilocalsize;
9579         projectionvector[2][1] = planes[1][2] * ilocalsize;
9580         projectionvector[2][2] = planes[2][2] * ilocalsize;
9581         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
9582         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
9583         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
9584         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
9585 }
9586 #endif
9587
9588         dynamic = model->surfmesh.isanimated;
9589         vertex3f = rsurface.modelvertex3f;
9590         numsurfacelist = model->nummodelsurfaces;
9591         surfacelist = model->sortedmodelsurfaces;
9592         surfaces = model->data_surfaces;
9593         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
9594         {
9595                 surfaceindex = surfacelist[surfacelistindex];
9596                 surface = surfaces + surfaceindex;
9597                 // skip transparent surfaces
9598                 texture = surface->texture;
9599                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9600                         continue;
9601                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
9602                         continue;
9603                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
9604                         continue;
9605                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
9606                 numvertices = surface->num_vertices;
9607                 numtriangles = surface->num_triangles;
9608                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
9609                 {
9610                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
9611                         {
9612                                 index = 3*e[cornerindex];
9613                                 VectorCopy(vertex3f + index, v[cornerindex]);
9614                         }
9615                         // cull backfaces
9616                         //TriangleNormal(v[0], v[1], v[2], normal);
9617                         //if (DotProduct(normal, localnormal) < 0.0f)
9618                         //      continue;
9619                         // clip by each of the box planes formed from the projection matrix
9620                         // if anything survives, we emit the decal
9621                         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]);
9622                         if (numpoints < 3)
9623                                 continue;
9624                         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]);
9625                         if (numpoints < 3)
9626                                 continue;
9627                         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]);
9628                         if (numpoints < 3)
9629                                 continue;
9630                         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]);
9631                         if (numpoints < 3)
9632                                 continue;
9633                         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]);
9634                         if (numpoints < 3)
9635                                 continue;
9636                         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]);
9637                         if (numpoints < 3)
9638                                 continue;
9639                         // some part of the triangle survived, so we have to accept it...
9640                         if (dynamic)
9641                         {
9642                                 // dynamic always uses the original triangle
9643                                 numpoints = 3;
9644                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9645                                 {
9646                                         index = 3*e[cornerindex];
9647                                         VectorCopy(vertex3f + index, v[cornerindex]);
9648                                 }
9649                         }
9650                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
9651                         {
9652                                 // convert vertex positions to texcoords
9653                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
9654                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
9655                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
9656                                 // calculate distance fade from the projection origin
9657                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
9658                                 f = bound(0.0f, f, 1.0f);
9659                                 c[cornerindex][0] = r * f;
9660                                 c[cornerindex][1] = g * f;
9661                                 c[cornerindex][2] = b * f;
9662                                 c[cornerindex][3] = 1.0f;
9663                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
9664                         }
9665                         if (dynamic)
9666                                 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);
9667                         else
9668                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
9669                                         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);
9670                 }
9671         }
9672 }
9673
9674 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
9675 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)
9676 {
9677         int renderentityindex;
9678         float worldmins[3];
9679         float worldmaxs[3];
9680         entity_render_t *ent;
9681
9682         if (!cl_decals_newsystem.integer)
9683                 return;
9684
9685         worldmins[0] = worldorigin[0] - worldsize;
9686         worldmins[1] = worldorigin[1] - worldsize;
9687         worldmins[2] = worldorigin[2] - worldsize;
9688         worldmaxs[0] = worldorigin[0] + worldsize;
9689         worldmaxs[1] = worldorigin[1] + worldsize;
9690         worldmaxs[2] = worldorigin[2] + worldsize;
9691
9692         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9693
9694         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
9695         {
9696                 ent = r_refdef.scene.entities[renderentityindex];
9697                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
9698                         continue;
9699
9700                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9701         }
9702 }
9703
9704 typedef struct r_decalsystem_splatqueue_s
9705 {
9706         vec3_t worldorigin;
9707         vec3_t worldnormal;
9708         float color[4];
9709         float tcrange[4];
9710         float worldsize;
9711         int decalsequence;
9712 }
9713 r_decalsystem_splatqueue_t;
9714
9715 int r_decalsystem_numqueued = 0;
9716 #define MAX_DECALSYSTEM_QUEUE 1024
9717 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
9718
9719 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)
9720 {
9721         r_decalsystem_splatqueue_t *queue;
9722
9723         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
9724                 return;
9725
9726         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
9727         VectorCopy(worldorigin, queue->worldorigin);
9728         VectorCopy(worldnormal, queue->worldnormal);
9729         Vector4Set(queue->color, r, g, b, a);
9730         Vector4Set(queue->tcrange, s1, t1, s2, t2);
9731         queue->worldsize = worldsize;
9732         queue->decalsequence = cl.decalsequence++;
9733 }
9734
9735 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
9736 {
9737         int i;
9738         r_decalsystem_splatqueue_t *queue;
9739
9740         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
9741                 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);
9742         r_decalsystem_numqueued = 0;
9743 }
9744
9745 extern cvar_t cl_decals_max;
9746 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
9747 {
9748         int i;
9749         decalsystem_t *decalsystem = &ent->decalsystem;
9750         int numdecals;
9751         int killsequence;
9752         tridecal_t *decal;
9753         float frametime;
9754         float lifetime;
9755
9756         if (!decalsystem->numdecals)
9757                 return;
9758
9759         if (r_showsurfaces.integer)
9760                 return;
9761
9762         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9763         {
9764                 R_DecalSystem_Reset(decalsystem);
9765                 return;
9766         }
9767
9768         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
9769         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
9770
9771         if (decalsystem->lastupdatetime)
9772                 frametime = (cl.time - decalsystem->lastupdatetime);
9773         else
9774                 frametime = 0;
9775         decalsystem->lastupdatetime = cl.time;
9776         decal = decalsystem->decals;
9777         numdecals = decalsystem->numdecals;
9778
9779         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9780         {
9781                 if (decal->color4ub[0][3])
9782                 {
9783                         decal->lived += frametime;
9784                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
9785                         {
9786                                 memset(decal, 0, sizeof(*decal));
9787                                 if (decalsystem->freedecal > i)
9788                                         decalsystem->freedecal = i;
9789                         }
9790                 }
9791         }
9792         decal = decalsystem->decals;
9793         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
9794                 numdecals--;
9795
9796         // collapse the array by shuffling the tail decals into the gaps
9797         for (;;)
9798         {
9799                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
9800                         decalsystem->freedecal++;
9801                 if (decalsystem->freedecal == numdecals)
9802                         break;
9803                 decal[decalsystem->freedecal] = decal[--numdecals];
9804         }
9805
9806         decalsystem->numdecals = numdecals;
9807
9808         if (numdecals <= 0)
9809         {
9810                 // if there are no decals left, reset decalsystem
9811                 R_DecalSystem_Reset(decalsystem);
9812         }
9813 }
9814
9815 extern skinframe_t *decalskinframe;
9816 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9817 {
9818         int i;
9819         decalsystem_t *decalsystem = &ent->decalsystem;
9820         int numdecals;
9821         tridecal_t *decal;
9822         float fadedelay;
9823         float faderate;
9824         float alpha;
9825         float *v3f;
9826         float *c4f;
9827         float *t2f;
9828         const int *e;
9829         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9830         int numtris = 0;
9831
9832         numdecals = decalsystem->numdecals;
9833         if (!numdecals)
9834                 return;
9835
9836         if (r_showsurfaces.integer)
9837                 return;
9838
9839         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9840         {
9841                 R_DecalSystem_Reset(decalsystem);
9842                 return;
9843         }
9844
9845         // if the model is static it doesn't matter what value we give for
9846         // wantnormals and wanttangents, so this logic uses only rules applicable
9847         // to a model, knowing that they are meaningless otherwise
9848         if (ent == r_refdef.scene.worldentity)
9849                 RSurf_ActiveWorldEntity();
9850         else
9851                 RSurf_ActiveModelEntity(ent, false, false, false);
9852
9853         decalsystem->lastupdatetime = cl.time;
9854         decal = decalsystem->decals;
9855
9856         fadedelay = cl_decals_time.value;
9857         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9858
9859         // update vertex positions for animated models
9860         v3f = decalsystem->vertex3f;
9861         c4f = decalsystem->color4f;
9862         t2f = decalsystem->texcoord2f;
9863         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9864         {
9865                 if (!decal->color4ub[0][3])
9866                         continue;
9867
9868                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9869                         continue;
9870
9871                 // update color values for fading decals
9872                 if (decal->lived >= cl_decals_time.value)
9873                 {
9874                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9875                         alpha *= (1.0f/255.0f);
9876                 }
9877                 else
9878                         alpha = 1.0f/255.0f;
9879
9880                 c4f[ 0] = decal->color4ub[0][0] * alpha;
9881                 c4f[ 1] = decal->color4ub[0][1] * alpha;
9882                 c4f[ 2] = decal->color4ub[0][2] * alpha;
9883                 c4f[ 3] = 1;
9884                 c4f[ 4] = decal->color4ub[1][0] * alpha;
9885                 c4f[ 5] = decal->color4ub[1][1] * alpha;
9886                 c4f[ 6] = decal->color4ub[1][2] * alpha;
9887                 c4f[ 7] = 1;
9888                 c4f[ 8] = decal->color4ub[2][0] * alpha;
9889                 c4f[ 9] = decal->color4ub[2][1] * alpha;
9890                 c4f[10] = decal->color4ub[2][2] * alpha;
9891                 c4f[11] = 1;
9892
9893                 t2f[0] = decal->texcoord2f[0][0];
9894                 t2f[1] = decal->texcoord2f[0][1];
9895                 t2f[2] = decal->texcoord2f[1][0];
9896                 t2f[3] = decal->texcoord2f[1][1];
9897                 t2f[4] = decal->texcoord2f[2][0];
9898                 t2f[5] = decal->texcoord2f[2][1];
9899
9900                 // update vertex positions for animated models
9901                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9902                 {
9903                         e = rsurface.modelelement3i + 3*decal->triangleindex;
9904                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9905                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9906                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9907                 }
9908                 else
9909                 {
9910                         VectorCopy(decal->vertex3f[0], v3f);
9911                         VectorCopy(decal->vertex3f[1], v3f + 3);
9912                         VectorCopy(decal->vertex3f[2], v3f + 6);
9913                 }
9914
9915                 v3f += 9;
9916                 c4f += 12;
9917                 t2f += 6;
9918                 numtris++;
9919         }
9920
9921         if (numtris > 0)
9922         {
9923                 r_refdef.stats.drawndecals += numtris;
9924
9925                 if (r_refdef.fogenabled)
9926                 {
9927                         switch(vid.renderpath)
9928                         {
9929                         case RENDERPATH_GL20:
9930                         case RENDERPATH_CGGL:
9931                         case RENDERPATH_GL13:
9932                         case RENDERPATH_GL11:
9933                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
9934                                 {
9935                                         alpha = RSurf_FogVertex(v3f);
9936                                         c4f[0] *= alpha;
9937                                         c4f[1] *= alpha;
9938                                         c4f[2] *= alpha;
9939                                 }
9940                                 break;
9941                         }
9942                 }
9943
9944                 // now render the decals all at once
9945                 // (this assumes they all use one particle font texture!)
9946                 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);
9947                 R_Mesh_ResetTextureState();
9948                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9949                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9950                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9951                 GL_DepthMask(false);
9952                 GL_DepthRange(0, 1);
9953                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9954                 GL_DepthTest(true);
9955                 GL_CullFace(GL_NONE);
9956                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9957                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
9958                 GL_LockArrays(0, numtris * 3);
9959                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9960                 GL_LockArrays(0, 0);
9961         }
9962 }
9963
9964 static void R_DrawModelDecals(void)
9965 {
9966         int i, numdecals;
9967
9968         // fade faster when there are too many decals
9969         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9970         for (i = 0;i < r_refdef.scene.numentities;i++)
9971                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9972
9973         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9974         for (i = 0;i < r_refdef.scene.numentities;i++)
9975                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9976                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9977
9978         R_DecalSystem_ApplySplatEntitiesQueue();
9979
9980         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9981         for (i = 0;i < r_refdef.scene.numentities;i++)
9982                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9983
9984         r_refdef.stats.totaldecals += numdecals;
9985
9986         if (r_showsurfaces.integer)
9987                 return;
9988
9989         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9990
9991         for (i = 0;i < r_refdef.scene.numentities;i++)
9992         {
9993                 if (!r_refdef.viewcache.entityvisible[i])
9994                         continue;
9995                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9996                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9997         }
9998 }
9999
10000 void R_DrawDebugModel(void)
10001 {
10002         entity_render_t *ent = rsurface.entity;
10003         int i, j, k, l, flagsmask;
10004         const int *elements;
10005         q3mbrush_t *brush;
10006         const msurface_t *surface;
10007         dp_model_t *model = ent->model;
10008         vec3_t v;
10009
10010         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10011
10012         R_Mesh_ColorPointer(NULL, 0, 0);
10013         R_Mesh_ResetTextureState();
10014         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10015         GL_DepthRange(0, 1);
10016         GL_DepthTest(!r_showdisabledepthtest.integer);
10017         GL_DepthMask(false);
10018         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10019
10020         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
10021         {
10022                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10023                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
10024                 {
10025                         if (brush->colbrushf && brush->colbrushf->numtriangles)
10026                         {
10027                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
10028                                 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);
10029                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
10030                         }
10031                 }
10032                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
10033                 {
10034                         if (surface->num_collisiontriangles)
10035                         {
10036                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
10037                                 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);
10038                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
10039                         }
10040                 }
10041         }
10042
10043         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10044
10045         if (r_showtris.integer || r_shownormals.integer)
10046         {
10047                 if (r_showdisabledepthtest.integer)
10048                 {
10049                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10050                         GL_DepthMask(false);
10051                 }
10052                 else
10053                 {
10054                         GL_BlendFunc(GL_ONE, GL_ZERO);
10055                         GL_DepthMask(true);
10056                 }
10057                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10058                 {
10059                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10060                                 continue;
10061                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10062                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10063                         {
10064                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
10065                                 if (r_showtris.value > 0)
10066                                 {
10067                                         if (!rsurface.texture->currentlayers->depthmask)
10068                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10069                                         else if (ent == r_refdef.scene.worldentity)
10070                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10071                                         else
10072                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10073                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
10074                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
10075                                         R_Mesh_ColorPointer(NULL, 0, 0);
10076                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
10077                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10078                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
10079                                         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);
10080                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10081                                         CHECKGLERROR
10082                                 }
10083                                 if (r_shownormals.value < 0)
10084                                 {
10085                                         qglBegin(GL_LINES);
10086                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10087                                         {
10088                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10089                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10090                                                 qglVertex3f(v[0], v[1], v[2]);
10091                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
10092                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10093                                                 qglVertex3f(v[0], v[1], v[2]);
10094                                         }
10095                                         qglEnd();
10096                                         CHECKGLERROR
10097                                 }
10098                                 if (r_shownormals.value > 0)
10099                                 {
10100                                         qglBegin(GL_LINES);
10101                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10102                                         {
10103                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10104                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10105                                                 qglVertex3f(v[0], v[1], v[2]);
10106                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
10107                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10108                                                 qglVertex3f(v[0], v[1], v[2]);
10109                                         }
10110                                         qglEnd();
10111                                         CHECKGLERROR
10112                                         qglBegin(GL_LINES);
10113                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10114                                         {
10115                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10116                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10117                                                 qglVertex3f(v[0], v[1], v[2]);
10118                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
10119                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10120                                                 qglVertex3f(v[0], v[1], v[2]);
10121                                         }
10122                                         qglEnd();
10123                                         CHECKGLERROR
10124                                         qglBegin(GL_LINES);
10125                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10126                                         {
10127                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
10128                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10129                                                 qglVertex3f(v[0], v[1], v[2]);
10130                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
10131                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10132                                                 qglVertex3f(v[0], v[1], v[2]);
10133                                         }
10134                                         qglEnd();
10135                                         CHECKGLERROR
10136                                 }
10137                         }
10138                 }
10139                 rsurface.texture = NULL;
10140         }
10141 }
10142
10143 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10144 int r_maxsurfacelist = 0;
10145 const msurface_t **r_surfacelist = NULL;
10146 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10147 {
10148         int i, j, endj, f, flagsmask;
10149         texture_t *t;
10150         dp_model_t *model = r_refdef.scene.worldmodel;
10151         msurface_t *surfaces;
10152         unsigned char *update;
10153         int numsurfacelist = 0;
10154         if (model == NULL)
10155                 return;
10156
10157         if (r_maxsurfacelist < model->num_surfaces)
10158         {
10159                 r_maxsurfacelist = model->num_surfaces;
10160                 if (r_surfacelist)
10161                         Mem_Free((msurface_t**)r_surfacelist);
10162                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10163         }
10164
10165         RSurf_ActiveWorldEntity();
10166
10167         surfaces = model->data_surfaces;
10168         update = model->brushq1.lightmapupdateflags;
10169
10170         // update light styles on this submodel
10171         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
10172         {
10173                 model_brush_lightstyleinfo_t *style;
10174                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10175                 {
10176                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
10177                         {
10178                                 int *list = style->surfacelist;
10179                                 style->value = r_refdef.scene.lightstylevalue[style->style];
10180                                 for (j = 0;j < style->numsurfaces;j++)
10181                                         update[list[j]] = true;
10182                         }
10183                 }
10184         }
10185
10186         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10187
10188         if (debug)
10189         {
10190                 R_DrawDebugModel();
10191                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10192                 return;
10193         }
10194
10195         f = 0;
10196         t = NULL;
10197         rsurface.uselightmaptexture = false;
10198         rsurface.texture = NULL;
10199         rsurface.rtlight = NULL;
10200         numsurfacelist = 0;
10201         // add visible surfaces to draw list
10202         for (i = 0;i < model->nummodelsurfaces;i++)
10203         {
10204                 j = model->sortedmodelsurfaces[i];
10205                 if (r_refdef.viewcache.world_surfacevisible[j])
10206                         r_surfacelist[numsurfacelist++] = surfaces + j;
10207         }
10208         // update lightmaps if needed
10209         if (update)
10210         {
10211                 int updated = 0;
10212                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10213                 {
10214                         if (r_refdef.viewcache.world_surfacevisible[j])
10215                         {
10216                                 if (update[j])
10217                                 {
10218                                         updated++;
10219                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
10220                                 }
10221                         }
10222                 }
10223                 if (updated)
10224                 {
10225                         int count = model->brushq3.num_mergedlightmaps;
10226                         for (i = 0;i < count;i++)
10227                         {
10228                                 if (model->brushq3.data_deluxemaps[i])
10229                                         R_FlushTexture(model->brushq3.data_deluxemaps[i]);
10230                                 if (model->brushq3.data_lightmaps[i])
10231                                         R_FlushTexture(model->brushq3.data_lightmaps[i]);
10232                         }
10233                 }
10234         }
10235         // don't do anything if there were no surfaces
10236         if (!numsurfacelist)
10237         {
10238                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10239                 return;
10240         }
10241         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
10242         GL_AlphaTest(false);
10243
10244         // add to stats if desired
10245         if (r_speeds.integer && !skysurfaces && !depthonly)
10246         {
10247                 r_refdef.stats.world_surfaces += numsurfacelist;
10248                 for (j = 0;j < numsurfacelist;j++)
10249                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
10250         }
10251
10252         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10253 }
10254
10255 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10256 {
10257         int i, j, endj, f, flagsmask;
10258         texture_t *t;
10259         dp_model_t *model = ent->model;
10260         msurface_t *surfaces;
10261         unsigned char *update;
10262         int numsurfacelist = 0;
10263         if (model == NULL)
10264                 return;
10265
10266         if (r_maxsurfacelist < model->num_surfaces)
10267         {
10268                 r_maxsurfacelist = model->num_surfaces;
10269                 if (r_surfacelist)
10270                         Mem_Free((msurface_t **)r_surfacelist);
10271                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10272         }
10273
10274         // if the model is static it doesn't matter what value we give for
10275         // wantnormals and wanttangents, so this logic uses only rules applicable
10276         // to a model, knowing that they are meaningless otherwise
10277         if (ent == r_refdef.scene.worldentity)
10278                 RSurf_ActiveWorldEntity();
10279         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10280                 RSurf_ActiveModelEntity(ent, false, false, false);
10281         else if (prepass)
10282                 RSurf_ActiveModelEntity(ent, true, true, true);
10283         else if (depthonly)
10284                 RSurf_ActiveModelEntity(ent, false, false, false);
10285         else
10286         {
10287                 switch (vid.renderpath)
10288                 {
10289                 case RENDERPATH_GL20:
10290                 case RENDERPATH_CGGL:
10291                         RSurf_ActiveModelEntity(ent, true, true, false);
10292                         break;
10293                 case RENDERPATH_GL13:
10294                 case RENDERPATH_GL11:
10295                         RSurf_ActiveModelEntity(ent, true, false, false);
10296                         break;
10297                 }
10298         }
10299
10300         surfaces = model->data_surfaces;
10301         update = model->brushq1.lightmapupdateflags;
10302
10303         // update light styles
10304         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
10305         {
10306                 model_brush_lightstyleinfo_t *style;
10307                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10308                 {
10309                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
10310                         {
10311                                 int *list = style->surfacelist;
10312                                 style->value = r_refdef.scene.lightstylevalue[style->style];
10313                                 for (j = 0;j < style->numsurfaces;j++)
10314                                         update[list[j]] = true;
10315                         }
10316                 }
10317         }
10318
10319         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10320
10321         if (debug)
10322         {
10323                 R_DrawDebugModel();
10324                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10325                 return;
10326         }
10327
10328         f = 0;
10329         t = NULL;
10330         rsurface.uselightmaptexture = false;
10331         rsurface.texture = NULL;
10332         rsurface.rtlight = NULL;
10333         numsurfacelist = 0;
10334         // add visible surfaces to draw list
10335         for (i = 0;i < model->nummodelsurfaces;i++)
10336                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
10337         // don't do anything if there were no surfaces
10338         if (!numsurfacelist)
10339         {
10340                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10341                 return;
10342         }
10343         // update lightmaps if needed
10344         if (update)
10345         {
10346                 int updated = 0;
10347                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10348                 {
10349                         if (update[j])
10350                         {
10351                                 updated++;
10352                                 R_BuildLightMap(ent, surfaces + j);
10353                         }
10354                 }
10355                 if (updated)
10356                 {
10357                         int count = model->brushq3.num_mergedlightmaps;
10358                         for (i = 0;i < count;i++)
10359                         {
10360                                 if (model->brushq3.data_deluxemaps[i])
10361                                         R_FlushTexture(model->brushq3.data_deluxemaps[i]);
10362                                 if (model->brushq3.data_lightmaps[i])
10363                                         R_FlushTexture(model->brushq3.data_lightmaps[i]);
10364                         }
10365                 }
10366         }
10367         if (update)
10368                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10369                         if (update[j])
10370                                 R_BuildLightMap(ent, surfaces + j);
10371         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
10372         GL_AlphaTest(false);
10373
10374         // add to stats if desired
10375         if (r_speeds.integer && !skysurfaces && !depthonly)
10376         {
10377                 r_refdef.stats.entities_surfaces += numsurfacelist;
10378                 for (j = 0;j < numsurfacelist;j++)
10379                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
10380         }
10381
10382         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10383 }
10384
10385 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
10386 {
10387         static texture_t texture;
10388         static msurface_t surface;
10389         const msurface_t *surfacelist = &surface;
10390
10391         // fake enough texture and surface state to render this geometry
10392
10393         texture.update_lastrenderframe = -1; // regenerate this texture
10394         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
10395         texture.currentskinframe = skinframe;
10396         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
10397         texture.specularscalemod = 1;
10398         texture.specularpowermod = 1;
10399
10400         surface.texture = &texture;
10401         surface.num_triangles = numtriangles;
10402         surface.num_firsttriangle = firsttriangle;
10403         surface.num_vertices = numvertices;
10404         surface.num_firstvertex = firstvertex;
10405
10406         // now render it
10407         rsurface.texture = R_GetCurrentTexture(surface.texture);
10408         rsurface.uselightmaptexture = false;
10409         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10410 }
10411
10412 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)
10413 {
10414         static msurface_t surface;
10415         const msurface_t *surfacelist = &surface;
10416
10417         // fake enough texture and surface state to render this geometry
10418
10419         surface.texture = texture;
10420         surface.num_triangles = numtriangles;
10421         surface.num_firsttriangle = firsttriangle;
10422         surface.num_vertices = numvertices;
10423         surface.num_firstvertex = firstvertex;
10424
10425         // now render it
10426         rsurface.texture = R_GetCurrentTexture(surface.texture);
10427         rsurface.uselightmaptexture = false;
10428         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10429 }