]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
allocate memory for big temporary storage arrays rather than using the
[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_PRECACHE | 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_PRECACHE | 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_PRECACHE | 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_PRECACHE | 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_PRECACHE | 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_PRECACHE | 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_PRECACHE | 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_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
454                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, 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 MODE_DEPTH_OR_SHADOW\n"
465 "#ifdef VERTEX_SHADER\n"
466 "void main(void)\n"
467 "{\n"
468 "       gl_Position = ftransform();\n"
469 "}\n"
470 "#endif\n"
471 "#else // !MODE_DEPTH_ORSHADOW\n"
472 "#ifdef MODE_SHOWDEPTH\n"
473 "#ifdef VERTEX_SHADER\n"
474 "void main(void)\n"
475 "{\n"
476 "       gl_Position = ftransform();\n"
477 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
478 "}\n"
479 "#endif\n"
480 "\n"
481 "#ifdef FRAGMENT_SHADER\n"
482 "void main(void)\n"
483 "{\n"
484 "       gl_FragColor = gl_Color;\n"
485 "}\n"
486 "#endif\n"
487 "#else // !MODE_SHOWDEPTH\n"
488 "#ifdef MODE_POSTPROCESS\n"
489 "varying vec2 TexCoord1;\n"
490 "varying vec2 TexCoord2;\n"
491 "\n"
492 "#ifdef VERTEX_SHADER\n"
493 "void main(void)\n"
494 "{\n"
495 "       gl_Position = ftransform();\n"
496 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
497 "#ifdef USEBLOOM\n"
498 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
499 "#endif\n"
500 "}\n"
501 "#endif\n"
502 "\n"
503 "#ifdef FRAGMENT_SHADER\n"
504 "uniform sampler2D Texture_First;\n"
505 "#ifdef USEBLOOM\n"
506 "uniform sampler2D Texture_Second;\n"
507 "#endif\n"
508 "#ifdef USEGAMMARAMPS\n"
509 "uniform sampler2D Texture_GammaRamps;\n"
510 "#endif\n"
511 "#ifdef USESATURATION\n"
512 "uniform float Saturation;\n"
513 "#endif\n"
514 "#ifdef USEVIEWTINT\n"
515 "uniform vec4 ViewTintColor;\n"
516 "#endif\n"
517 "//uncomment these if you want to use them:\n"
518 "uniform vec4 UserVec1;\n"
519 "// uniform vec4 UserVec2;\n"
520 "// uniform vec4 UserVec3;\n"
521 "// uniform vec4 UserVec4;\n"
522 "// uniform float ClientTime;\n"
523 "uniform vec2 PixelSize;\n"
524 "void main(void)\n"
525 "{\n"
526 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
527 "#ifdef USEBLOOM\n"
528 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
529 "#endif\n"
530 "#ifdef USEVIEWTINT\n"
531 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
532 "#endif\n"
533 "\n"
534 "#ifdef USEPOSTPROCESSING\n"
535 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
536 "// 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"
537 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
538 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
539 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
540 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
541 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
542 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
543 "#endif\n"
544 "\n"
545 "#ifdef USESATURATION\n"
546 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
547 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
548 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
549 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
550 "#endif\n"
551 "\n"
552 "#ifdef USEGAMMARAMPS\n"
553 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
554 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
555 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
556 "#endif\n"
557 "}\n"
558 "#endif\n"
559 "#else // !MODE_POSTPROCESS\n"
560 "#ifdef MODE_GENERIC\n"
561 "#ifdef USEDIFFUSE\n"
562 "varying vec2 TexCoord1;\n"
563 "#endif\n"
564 "#ifdef USESPECULAR\n"
565 "varying vec2 TexCoord2;\n"
566 "#endif\n"
567 "#ifdef VERTEX_SHADER\n"
568 "void main(void)\n"
569 "{\n"
570 "       gl_FrontColor = gl_Color;\n"
571 "#ifdef USEDIFFUSE\n"
572 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
573 "#endif\n"
574 "#ifdef USESPECULAR\n"
575 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
576 "#endif\n"
577 "       gl_Position = ftransform();\n"
578 "}\n"
579 "#endif\n"
580 "\n"
581 "#ifdef FRAGMENT_SHADER\n"
582 "#ifdef USEDIFFUSE\n"
583 "uniform sampler2D Texture_First;\n"
584 "#endif\n"
585 "#ifdef USESPECULAR\n"
586 "uniform sampler2D Texture_Second;\n"
587 "#endif\n"
588 "\n"
589 "void main(void)\n"
590 "{\n"
591 "       gl_FragColor = gl_Color;\n"
592 "#ifdef USEDIFFUSE\n"
593 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
594 "#endif\n"
595 "\n"
596 "#ifdef USESPECULAR\n"
597 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
598 "#endif\n"
599 "#ifdef USECOLORMAPPING\n"
600 "       gl_FragColor *= tex2;\n"
601 "#endif\n"
602 "#ifdef USEGLOW\n"
603 "       gl_FragColor += tex2;\n"
604 "#endif\n"
605 "#ifdef USEVERTEXTEXTUREBLEND\n"
606 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
607 "#endif\n"
608 "}\n"
609 "#endif\n"
610 "#else // !MODE_GENERIC\n"
611 "#ifdef MODE_BLOOMBLUR\n"
612 "varying TexCoord;\n"
613 "#ifdef VERTEX_SHADER\n"
614 "void main(void)\n"
615 "{\n"
616 "       gl_FrontColor = gl_Color;\n"
617 "       TexCoord = gl_MultiTexCoord0.xy;\n"
618 "       gl_Position = ftransform();\n"
619 "}\n"
620 "#endif\n"
621 "\n"
622 "#ifdef FRAGMENT_SHADER\n"
623 "uniform sampler2D Texture_First;\n"
624 "uniform vec4 BloomBlur_Parameters;\n"
625 "\n"
626 "void main(void)\n"
627 "{\n"
628 "       int i;\n"
629 "       vec2 tc = TexCoord;\n"
630 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
631 "       tc += BloomBlur_Parameters.xy;\n"
632 "       for (i = 1;i < SAMPLES;i++)\n"
633 "       {\n"
634 "               color += texture2D(Texture_First, tc).rgb;\n"
635 "               tc += BloomBlur_Parameters.xy;\n"
636 "       }\n"
637 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
638 "}\n"
639 "#endif\n"
640 "#else // !MODE_BLOOMBLUR\n"
641 "#ifdef MODE_REFRACTION\n"
642 "varying vec2 TexCoord;\n"
643 "varying vec4 ModelViewProjectionPosition;\n"
644 "uniform mat4 TexMatrix;\n"
645 "#ifdef VERTEX_SHADER\n"
646 "\n"
647 "void main(void)\n"
648 "{\n"
649 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
650 "       gl_Position = ftransform();\n"
651 "       ModelViewProjectionPosition = gl_Position;\n"
652 "}\n"
653 "#endif\n"
654 "\n"
655 "#ifdef FRAGMENT_SHADER\n"
656 "uniform sampler2D Texture_Normal;\n"
657 "uniform sampler2D Texture_Refraction;\n"
658 "uniform sampler2D Texture_Reflection;\n"
659 "\n"
660 "uniform vec4 DistortScaleRefractReflect;\n"
661 "uniform vec4 ScreenScaleRefractReflect;\n"
662 "uniform vec4 ScreenCenterRefractReflect;\n"
663 "uniform vec4 RefractColor;\n"
664 "uniform vec4 ReflectColor;\n"
665 "uniform float ReflectFactor;\n"
666 "uniform float ReflectOffset;\n"
667 "\n"
668 "void main(void)\n"
669 "{\n"
670 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
671 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
672 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
673 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
674 "       // FIXME temporary hack to detect the case that the reflection\n"
675 "       // gets blackened at edges due to leaving the area that contains actual\n"
676 "       // content.\n"
677 "       // Remove this 'ack once we have a better way to stop this thing from\n"
678 "       // 'appening.\n"
679 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
680 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
681 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
682 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
683 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
684 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
685 "}\n"
686 "#endif\n"
687 "#else // !MODE_REFRACTION\n"
688 "#ifdef MODE_WATER\n"
689 "varying vec2 TexCoord;\n"
690 "varying vec3 EyeVector;\n"
691 "varying vec4 ModelViewProjectionPosition;\n"
692 "#ifdef VERTEX_SHADER\n"
693 "uniform vec3 EyePosition;\n"
694 "uniform mat4 TexMatrix;\n"
695 "\n"
696 "void main(void)\n"
697 "{\n"
698 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
699 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
700 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
701 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
702 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
703 "       gl_Position = ftransform();\n"
704 "       ModelViewProjectionPosition = gl_Position;\n"
705 "}\n"
706 "#endif\n"
707 "\n"
708 "#ifdef FRAGMENT_SHADER\n"
709 "uniform sampler2D Texture_Normal;\n"
710 "uniform sampler2D Texture_Refraction;\n"
711 "uniform sampler2D Texture_Reflection;\n"
712 "\n"
713 "uniform vec4 DistortScaleRefractReflect;\n"
714 "uniform vec4 ScreenScaleRefractReflect;\n"
715 "uniform vec4 ScreenCenterRefractReflect;\n"
716 "uniform vec4 RefractColor;\n"
717 "uniform vec4 ReflectColor;\n"
718 "uniform float ReflectFactor;\n"
719 "uniform float ReflectOffset;\n"
720 "\n"
721 "void main(void)\n"
722 "{\n"
723 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
724 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
725 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
726 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
727 "       // FIXME temporary hack to detect the case that the reflection\n"
728 "       // gets blackened at edges due to leaving the area that contains actual\n"
729 "       // content.\n"
730 "       // Remove this 'ack once we have a better way to stop this thing from\n"
731 "       // 'appening.\n"
732 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
733 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
734 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
735 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
736 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
737 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
738 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
739 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
740 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
741 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
742 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
743 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
744 "}\n"
745 "#endif\n"
746 "#else // !MODE_WATER\n"
747 "\n"
748 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
749 "# extension GL_ARB_texture_rectangle : enable\n"
750 "#endif\n"
751 "\n"
752 "#ifdef USESHADOWMAP2D\n"
753 "# ifdef GL_EXT_gpu_shader4\n"
754 "#   extension GL_EXT_gpu_shader4 : enable\n"
755 "# endif\n"
756 "# ifdef GL_ARB_texture_gather\n"
757 "#   extension GL_ARB_texture_gather : enable\n"
758 "# else\n"
759 "#   ifdef GL_AMD_texture_texture4\n"
760 "#     extension GL_AMD_texture_texture4 : enable\n"
761 "#   endif\n"
762 "# endif\n"
763 "#endif\n"
764 "\n"
765 "#ifdef USESHADOWMAPCUBE\n"
766 "# extension GL_EXT_gpu_shader4 : enable\n"
767 "#endif\n"
768 "\n"
769 "#ifdef USESHADOWSAMPLER\n"
770 "# extension GL_ARB_shadow : enable\n"
771 "#endif\n"
772 "\n"
773 "// common definitions between vertex shader and fragment shader:\n"
774 "\n"
775 "//#ifdef __GLSL_CG_DATA_TYPES\n"
776 "//# define myhalf half\n"
777 "//# define myhalf2 half2\n"
778 "//# define myhalf3half3\n"
779 "//# define myhalf4 half4\n"
780 "//#else\n"
781 "# define myhalf float\n"
782 "# define myhalf2 vec2\n"
783 "# define myhalf3 vec3\n"
784 "# define myhalf4 vec4\n"
785 "//#endif\n"
786 "\n"
787 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
788 "# define USEFOG\n"
789 "#endif\n"
790 "\n"
791 "varying vec2 TexCoord;\n"
792 "#ifdef USEVERTEXTEXTUREBLEND\n"
793 "varying vec2 TexCoord2;\n"
794 "#endif\n"
795 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
796 "#define USELIGHTMAP\n"
797 "varying vec2 TexCoordLightmap;\n"
798 "#endif\n"
799 "\n"
800 "#ifdef MODE_LIGHTSOURCE\n"
801 "varying vec3 CubeVector;\n"
802 "#endif\n"
803 "\n"
804 "#ifdef MODE_LIGHTSOURCE\n"
805 "varying vec3 LightVector;\n"
806 "#endif\n"
807 "#if defined(MODE_LIGHTDIRECTION)\n"
808 "varying vec3 LightVector;\n"
809 "#endif\n"
810 "\n"
811 "#if defined(USEOFFSETMAPPING) || defined(USESPECULAR)\n"
812 "//#if defined(USEOFFSETMAPPING) || defined(USESPECULAR) || defined(MODE_LIGHTDIRECTION) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
813 "#define USEEYEVECTOR\n"
814 "varying vec3 EyeVector;\n"
815 "#endif\n"
816 "#ifdef USEFOG\n"
817 "varying vec3 EyeVectorModelSpace;\n"
818 "varying float FogPlaneVertexDist;\n"
819 "#endif\n"
820 "\n"
821 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
822 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
823 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
824 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
825 "#endif\n"
826 "\n"
827 "#ifdef USEREFLECTION\n"
828 "varying vec4 ModelViewProjectionPosition;\n"
829 "#endif\n"
830 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
831 "uniform vec3 LightPosition;\n"
832 "varying vec4 ModelViewPosition;\n"
833 "#endif\n"
834 "\n"
835 "#ifdef MODE_LIGHTSOURCE\n"
836 "uniform vec3 LightPosition;\n"
837 "#endif\n"
838 "uniform vec3 EyePosition;\n"
839 "#ifdef MODE_LIGHTDIRECTION\n"
840 "uniform vec3 LightDir;\n"
841 "#endif\n"
842 "uniform vec4 FogPlane;\n"
843 "\n"
844 "\n"
845 "\n"
846 "\n"
847 "\n"
848 "// vertex shader specific:\n"
849 "#ifdef VERTEX_SHADER\n"
850 "\n"
851 "// 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"
852 "\n"
853 "#ifdef MODE_DEFERREDGEOMETRY\n"
854 "uniform mat4 TexMatrix;\n"
855 "#ifdef USEVERTEXTEXTUREBLEND\n"
856 "uniform mat4 BackgroundTexMatrix;\n"
857 "#endif\n"
858 "void main(void)\n"
859 "{\n"
860 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
861 "#ifdef USEVERTEXTEXTUREBLEND\n"
862 "       gl_FrontColor = gl_Color;\n"
863 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
864 "#endif\n"
865 "\n"
866 "       // transform unnormalized eye direction into tangent space\n"
867 "#ifdef USEOFFSETMAPPING\n"
868 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
869 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
870 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
871 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
872 "#endif\n"
873 "\n"
874 "       VectorS = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz).xyz;\n"
875 "       VectorT = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz).xyz;\n"
876 "       VectorR = normalize(gl_NormalMatrix * gl_MultiTexCoord3.xyz).xyz;\n"
877 "       gl_Position = ftransform();\n"
878 "}\n"
879 "#else // !MODE_DEFERREDGEOMETRY\n"
880 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
881 "void main(void)\n"
882 "{\n"
883 "       ModelViewPosition = gl_ModelViewMatrix * gl_Vertex;\n"
884 "       gl_Position = ftransform();\n"
885 "}\n"
886 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
887 "uniform mat4 TexMatrix;\n"
888 "#ifdef USEVERTEXTEXTUREBLEND\n"
889 "uniform mat4 BackgroundTexMatrix;\n"
890 "#endif\n"
891 "#ifdef MODE_LIGHTSOURCE\n"
892 "uniform mat4 ModelToLight;\n"
893 "#endif\n"
894 "void main(void)\n"
895 "{\n"
896 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
897 "       gl_FrontColor = gl_Color;\n"
898 "#endif\n"
899 "       // copy the surface texcoord\n"
900 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
901 "#ifdef USEVERTEXTEXTUREBLEND\n"
902 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
903 "#endif\n"
904 "#ifdef USELIGHTMAP\n"
905 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
906 "#endif\n"
907 "\n"
908 "#ifdef MODE_LIGHTSOURCE\n"
909 "       // transform vertex position into light attenuation/cubemap space\n"
910 "       // (-1 to +1 across the light box)\n"
911 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
912 "\n"
913 "# ifdef USEDIFFUSE\n"
914 "       // transform unnormalized light direction into tangent space\n"
915 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
916 "       //  normalize it per pixel)\n"
917 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
918 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
919 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
920 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
921 "# endif\n"
922 "#endif\n"
923 "\n"
924 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
925 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
926 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
927 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
928 "#endif\n"
929 "\n"
930 "       // transform unnormalized eye direction into tangent space\n"
931 "#ifdef USEEYEVECTOR\n"
932 "#ifndef USEFOG\n"
933 "       vec3 EyeVectorModelSpace;\n"
934 "#endif\n"
935 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
936 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
937 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
938 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
939 "#endif\n"
940 "\n"
941 "#ifdef USEFOG\n"
942 "#ifndef USEEYEVECTOR\n"
943 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
944 "#endif\n"
945 "       FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
946 "#endif\n"
947 "\n"
948 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
949 "       VectorS = gl_MultiTexCoord1.xyz;\n"
950 "       VectorT = gl_MultiTexCoord2.xyz;\n"
951 "       VectorR = gl_MultiTexCoord3.xyz;\n"
952 "#endif\n"
953 "\n"
954 "//#if defined(USEREFLECTION)\n"
955 "//     ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
956 "//     //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
957 "//     //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
958 "//#endif\n"
959 "\n"
960 "// transform vertex to camera space, using ftransform to match non-VS\n"
961 "       // rendering\n"
962 "       gl_Position = ftransform();\n"
963 "\n"
964 "#ifdef USEREFLECTION\n"
965 "       ModelViewProjectionPosition = gl_Position;\n"
966 "#endif\n"
967 "}\n"
968 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
969 "#endif // !MODE_DEFERREDGEOMETRY\n"
970 "\n"
971 "#endif // VERTEX_SHADER\n"
972 "\n"
973 "\n"
974 "\n"
975 "\n"
976 "// fragment shader specific:\n"
977 "#ifdef FRAGMENT_SHADER\n"
978 "\n"
979 "uniform sampler2D Texture_Normal;\n"
980 "uniform sampler2D Texture_Color;\n"
981 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
982 "uniform sampler2D Texture_Gloss;\n"
983 "//#endif\n"
984 "#ifdef USEGLOW\n"
985 "uniform sampler2D Texture_Glow;\n"
986 "#endif\n"
987 "#ifdef USEVERTEXTEXTUREBLEND\n"
988 "uniform sampler2D Texture_SecondaryNormal;\n"
989 "uniform sampler2D Texture_SecondaryColor;\n"
990 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
991 "uniform sampler2D Texture_SecondaryGloss;\n"
992 "//#endif\n"
993 "#ifdef USEGLOW\n"
994 "uniform sampler2D Texture_SecondaryGlow;\n"
995 "#endif\n"
996 "#endif\n"
997 "#ifdef USECOLORMAPPING\n"
998 "uniform sampler2D Texture_Pants;\n"
999 "uniform sampler2D Texture_Shirt;\n"
1000 "#endif\n"
1001 "#ifdef USEFOG\n"
1002 "uniform sampler2D Texture_FogMask;\n"
1003 "#endif\n"
1004 "#ifdef USELIGHTMAP\n"
1005 "uniform sampler2D Texture_Lightmap;\n"
1006 "#endif\n"
1007 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1008 "uniform sampler2D Texture_Deluxemap;\n"
1009 "#endif\n"
1010 "#ifdef USEREFLECTION\n"
1011 "uniform sampler2D Texture_Reflection;\n"
1012 "#endif\n"
1013 "\n"
1014 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1015 "uniform sampler2DRect Texture_ScreenDepth;\n"
1016 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
1017 "#endif\n"
1018 "#ifdef USEDEFERREDLIGHTMAP\n"
1019 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
1020 "uniform sampler2DRect Texture_ScreenSpecular;\n"
1021 "#endif\n"
1022 "\n"
1023 "uniform myhalf3 Color_Pants;\n"
1024 "uniform myhalf3 Color_Shirt;\n"
1025 "uniform myhalf3 FogColor;\n"
1026 "\n"
1027 "#ifdef USEFOG\n"
1028 "uniform float FogRangeRecip;\n"
1029 "uniform float FogPlaneViewDist;\n"
1030 "uniform float FogHeightFade;\n"
1031 "myhalf FogVertex(void)\n"
1032 "{\n"
1033 "       float fogfrac;\n"
1034 "#ifdef USEFOGOUTSIDE\n"
1035 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1036 "#else\n"
1037 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1038 "#endif\n"
1039 "       return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1040 "}\n"
1041 "#endif\n"
1042 "\n"
1043 "#ifdef USEOFFSETMAPPING\n"
1044 "uniform float OffsetMapping_Scale;\n"
1045 "vec2 OffsetMapping(vec2 TexCoord)\n"
1046 "{\n"
1047 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1048 "       // 14 sample relief mapping: linear search and then binary search\n"
1049 "       // this basically steps forward a small amount repeatedly until it finds\n"
1050 "       // itself inside solid, then jitters forward and back using decreasing\n"
1051 "       // amounts to find the impact\n"
1052 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1053 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1054 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1055 "       vec3 RT = vec3(TexCoord, 1);\n"
1056 "       OffsetVector *= 0.1;\n"
1057 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1058 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1059 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1060 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1061 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1062 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1063 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1064 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1065 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1066 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1067 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1068 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1069 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1070 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1071 "       return RT.xy;\n"
1072 "#else\n"
1073 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1074 "       // this basically moves forward the full distance, and then backs up based\n"
1075 "       // on height of samples\n"
1076 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1077 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1078 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1079 "       TexCoord += OffsetVector;\n"
1080 "       OffsetVector *= 0.333;\n"
1081 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1082 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1083 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1084 "       return TexCoord;\n"
1085 "#endif\n"
1086 "}\n"
1087 "#endif // USEOFFSETMAPPING\n"
1088 "\n"
1089 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1090 "uniform sampler2D Texture_Attenuation;\n"
1091 "uniform samplerCube Texture_Cube;\n"
1092 "\n"
1093 "#ifdef USESHADOWMAPRECT\n"
1094 "# ifdef USESHADOWSAMPLER\n"
1095 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1096 "# else\n"
1097 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1098 "# endif\n"
1099 "#endif\n"
1100 "\n"
1101 "#ifdef USESHADOWMAP2D\n"
1102 "# ifdef USESHADOWSAMPLER\n"
1103 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1104 "# else\n"
1105 "uniform sampler2D Texture_ShadowMap2D;\n"
1106 "# endif\n"
1107 "#endif\n"
1108 "\n"
1109 "#ifdef USESHADOWMAPVSDCT\n"
1110 "uniform samplerCube Texture_CubeProjection;\n"
1111 "#endif\n"
1112 "\n"
1113 "#ifdef USESHADOWMAPCUBE\n"
1114 "# ifdef USESHADOWSAMPLER\n"
1115 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1116 "# else\n"
1117 "uniform samplerCube Texture_ShadowMapCube;\n"
1118 "# endif\n"
1119 "#endif\n"
1120 "\n"
1121 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1122 "uniform vec2 ShadowMap_TextureScale;\n"
1123 "uniform vec4 ShadowMap_Parameters;\n"
1124 "#endif\n"
1125 "\n"
1126 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1127 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1128 "{\n"
1129 "       vec3 adir = abs(dir);\n"
1130 "# ifndef USESHADOWMAPVSDCT\n"
1131 "       vec2 tc;\n"
1132 "       vec2 offset;\n"
1133 "       float ma;\n"
1134 "       if (adir.x > adir.y)\n"
1135 "       {\n"
1136 "               if (adir.x > adir.z) // X\n"
1137 "               {\n"
1138 "                       ma = adir.x;\n"
1139 "                       tc = dir.zy;\n"
1140 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1141 "               }\n"
1142 "               else // Z\n"
1143 "               {\n"
1144 "                       ma = adir.z;\n"
1145 "                       tc = dir.xy;\n"
1146 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1147 "               }\n"
1148 "       }\n"
1149 "       else\n"
1150 "       {\n"
1151 "               if (adir.y > adir.z) // Y\n"
1152 "               {\n"
1153 "                       ma = adir.y;\n"
1154 "                       tc = dir.xz;\n"
1155 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1156 "               }\n"
1157 "               else // Z\n"
1158 "               {\n"
1159 "                       ma = adir.z;\n"
1160 "                       tc = dir.xy;\n"
1161 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1162 "               }\n"
1163 "       }\n"
1164 "\n"
1165 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1166 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1167 "       stc.z += ShadowMap_Parameters.z;\n"
1168 "       return stc;\n"
1169 "# else\n"
1170 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1171 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1172 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1173 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1174 "       stc.z += ShadowMap_Parameters.z;\n"
1175 "       return stc;\n"
1176 "# endif\n"
1177 "}\n"
1178 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1179 "\n"
1180 "#ifdef USESHADOWMAPCUBE\n"
1181 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1182 "{\n"
1183 "    vec3 adir = abs(dir);\n"
1184 "    return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1185 "}\n"
1186 "#endif\n"
1187 "\n"
1188 "# ifdef USESHADOWMAPRECT\n"
1189 "float ShadowMapCompare(vec3 dir)\n"
1190 "{\n"
1191 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1192 "       float f;\n"
1193 "#  ifdef USESHADOWSAMPLER\n"
1194 "\n"
1195 "#    ifdef USESHADOWMAPPCF\n"
1196 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1197 "    f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1198 "#    else\n"
1199 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1200 "#    endif\n"
1201 "\n"
1202 "#  else\n"
1203 "\n"
1204 "#    ifdef USESHADOWMAPPCF\n"
1205 "#      if USESHADOWMAPPCF > 1\n"
1206 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1207 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1208 "    vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1209 "    vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1210 "    vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1211 "    vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1212 "    vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1213 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1214 "#      else\n"
1215 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1216 "    vec2 offset = fract(shadowmaptc.xy);\n"
1217 "    vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1218 "    vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1219 "    vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1220 "    vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1221 "    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1222 "#      endif\n"
1223 "#    else\n"
1224 "    f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1225 "#    endif\n"
1226 "\n"
1227 "#  endif\n"
1228 "       return f;\n"
1229 "}\n"
1230 "# endif\n"
1231 "\n"
1232 "# ifdef USESHADOWMAP2D\n"
1233 "float ShadowMapCompare(vec3 dir)\n"
1234 "{\n"
1235 "    vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1236 "    float f;\n"
1237 "\n"
1238 "#  ifdef USESHADOWSAMPLER\n"
1239 "#    ifdef USESHADOWMAPPCF\n"
1240 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1241 "    vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1242 "    f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1243 "#    else\n"
1244 "    f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1245 "#    endif\n"
1246 "#  else\n"
1247 "#    ifdef USESHADOWMAPPCF\n"
1248 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1249 "#      ifdef GL_ARB_texture_gather\n"
1250 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1251 "#      else\n"
1252 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1253 "#      endif\n"
1254 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1255 "    center *= ShadowMap_TextureScale;\n"
1256 "    vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1257 "    vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1258 "    vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1259 "    vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1260 "    vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1261 "                mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1262 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1263 "#     else\n"
1264 "#      ifdef GL_EXT_gpu_shader4\n"
1265 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1266 "#      else\n"
1267 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1268 "#      endif\n"
1269 "#      if USESHADOWMAPPCF > 1\n"
1270 "    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1271 "    center *= ShadowMap_TextureScale;\n"
1272 "    vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1273 "    vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1274 "    vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1275 "    vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1276 "    vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1277 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1278 "#      else\n"
1279 "    vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1280 "    vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1281 "    vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1282 "    vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1283 "    vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1284 "    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1285 "#      endif\n"
1286 "#     endif\n"
1287 "#    else\n"
1288 "    f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1289 "#    endif\n"
1290 "#  endif\n"
1291 "    return f;\n"
1292 "}\n"
1293 "# endif\n"
1294 "\n"
1295 "# ifdef USESHADOWMAPCUBE\n"
1296 "float ShadowMapCompare(vec3 dir)\n"
1297 "{\n"
1298 "    // apply depth texture cubemap as light filter\n"
1299 "    vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1300 "    float f;\n"
1301 "#  ifdef USESHADOWSAMPLER\n"
1302 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1303 "#  else\n"
1304 "    f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1305 "#  endif\n"
1306 "    return f;\n"
1307 "}\n"
1308 "# endif\n"
1309 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1310 "\n"
1311 "#ifdef MODE_DEFERREDGEOMETRY\n"
1312 "void main(void)\n"
1313 "{\n"
1314 "#ifdef USEOFFSETMAPPING\n"
1315 "       // apply offsetmapping\n"
1316 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1317 "#define TexCoord TexCoordOffset\n"
1318 "#endif\n"
1319 "\n"
1320 "#ifdef USEALPHAKILL\n"
1321 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1322 "               discard;\n"
1323 "#endif\n"
1324 "\n"
1325 "#ifdef USEVERTEXTEXTUREBLEND\n"
1326 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1327 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1328 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1329 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1330 "#endif\n"
1331 "\n"
1332 "#ifdef USEVERTEXTEXTUREBLEND\n"
1333 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1334 "#else\n"
1335 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1336 "#endif\n"
1337 "\n"
1338 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1339 "}\n"
1340 "#else // !MODE_DEFERREDGEOMETRY\n"
1341 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1342 "uniform mat4 ViewToLight;\n"
1343 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1344 "uniform vec2 ScreenToDepth;\n"
1345 "uniform myhalf3 DeferredColor_Ambient;\n"
1346 "uniform myhalf3 DeferredColor_Diffuse;\n"
1347 "#ifdef USESPECULAR\n"
1348 "uniform myhalf3 DeferredColor_Specular;\n"
1349 "uniform myhalf SpecularPower;\n"
1350 "#endif\n"
1351 "void main(void)\n"
1352 "{\n"
1353 "       // calculate viewspace pixel position\n"
1354 "       vec3 position;\n"
1355 "       position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1356 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1357 "       // decode viewspace pixel normal\n"
1358 "       myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1359 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1360 "       // surfacenormal = pixel normal in viewspace\n"
1361 "       // LightVector = pixel to light in viewspace\n"
1362 "       // CubeVector = position in lightspace\n"
1363 "       // eyevector = pixel to view in viewspace\n"
1364 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1365 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1366 "#ifdef USEDIFFUSE\n"
1367 "       // calculate diffuse shading\n"
1368 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1369 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1370 "#endif\n"
1371 "#ifdef USESPECULAR\n"
1372 "       // calculate directional shading\n"
1373 "       vec3 eyevector = position * -1.0;\n"
1374 "#  ifdef USEEXACTSPECULARMATH\n"
1375 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1376 "#  else\n"
1377 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1378 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1379 "#  endif\n"
1380 "#endif\n"
1381 "\n"
1382 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1383 "       fade *= ShadowMapCompare(CubeVector);\n"
1384 "#endif\n"
1385 "\n"
1386 "#ifdef USEDIFFUSE\n"
1387 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1388 "#else\n"
1389 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1390 "#endif\n"
1391 "#ifdef USESPECULAR\n"
1392 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1393 "#else\n"
1394 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1395 "#endif\n"
1396 "\n"
1397 "# ifdef USECUBEFILTER\n"
1398 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1399 "       gl_FragData[0] *= cubecolor;\n"
1400 "       gl_FragData[1] *= cubecolor;\n"
1401 "# endif\n"
1402 "}\n"
1403 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1404 "#ifdef USEDEFERREDLIGHTMAP\n"
1405 "uniform myhalf3 DeferredMod_Diffuse;\n"
1406 "uniform myhalf3 DeferredMod_Specular;\n"
1407 "#endif\n"
1408 "uniform myhalf3 Color_Ambient;\n"
1409 "uniform myhalf3 Color_Diffuse;\n"
1410 "uniform myhalf3 Color_Specular;\n"
1411 "uniform myhalf SpecularPower;\n"
1412 "#ifdef USEGLOW\n"
1413 "uniform myhalf3 Color_Glow;\n"
1414 "#endif\n"
1415 "uniform myhalf Alpha;\n"
1416 "#ifdef USEREFLECTION\n"
1417 "uniform vec4 DistortScaleRefractReflect;\n"
1418 "uniform vec4 ScreenScaleRefractReflect;\n"
1419 "uniform vec4 ScreenCenterRefractReflect;\n"
1420 "uniform myhalf4 ReflectColor;\n"
1421 "#endif\n"
1422 "#ifdef MODE_LIGHTDIRECTION\n"
1423 "uniform myhalf3 LightColor;\n"
1424 "#endif\n"
1425 "#ifdef MODE_LIGHTSOURCE\n"
1426 "uniform myhalf3 LightColor;\n"
1427 "#endif\n"
1428 "void main(void)\n"
1429 "{\n"
1430 "#ifdef USEOFFSETMAPPING\n"
1431 "       // apply offsetmapping\n"
1432 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1433 "#define TexCoord TexCoordOffset\n"
1434 "#endif\n"
1435 "\n"
1436 "       // combine the diffuse textures (base, pants, shirt)\n"
1437 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1438 "#ifdef USEALPHAKILL\n"
1439 "       if (color.a < 0.5)\n"
1440 "               discard;\n"
1441 "#endif\n"
1442 "       color.a *= Alpha;\n"
1443 "#ifdef USECOLORMAPPING\n"
1444 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1445 "#endif\n"
1446 "#ifdef USEVERTEXTEXTUREBLEND\n"
1447 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1448 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1449 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1450 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1451 "       color.a = 1.0;\n"
1452 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1453 "#endif\n"
1454 "\n"
1455 "       // get the surface normal\n"
1456 "#ifdef USEVERTEXTEXTUREBLEND\n"
1457 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1458 "#else\n"
1459 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1460 "#endif\n"
1461 "\n"
1462 "       // get the material colors\n"
1463 "       myhalf3 diffusetex = color.rgb;\n"
1464 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1465 "# ifdef USEVERTEXTEXTUREBLEND\n"
1466 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1467 "# else\n"
1468 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1469 "# endif\n"
1470 "#endif\n"
1471 "\n"
1472 "\n"
1473 "\n"
1474 "\n"
1475 "#ifdef MODE_LIGHTSOURCE\n"
1476 "       // light source\n"
1477 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1478 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1479 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1480 "#ifdef USESPECULAR\n"
1481 "#ifdef USEEXACTSPECULARMATH\n"
1482 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1483 "#else\n"
1484 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1485 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1486 "#endif\n"
1487 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1488 "#endif\n"
1489 "       color.rgb *= LightColor;\n"
1490 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1491 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1492 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1493 "#endif\n"
1494 "# ifdef USECUBEFILTER\n"
1495 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1496 "# endif\n"
1497 "#endif // MODE_LIGHTSOURCE\n"
1498 "\n"
1499 "\n"
1500 "\n"
1501 "\n"
1502 "#ifdef MODE_LIGHTDIRECTION\n"
1503 "#define SHADING\n"
1504 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1505 "#define lightcolor LightColor\n"
1506 "#endif // MODE_LIGHTDIRECTION\n"
1507 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1508 "#define SHADING\n"
1509 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1510 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1511 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1512 "       // convert modelspace light vector to tangentspace\n"
1513 "       myhalf3 lightnormal;\n"
1514 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1515 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1516 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1517 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1518 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1519 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1520 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1521 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1522 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1523 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1524 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1525 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1526 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1527 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1528 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1529 "#define SHADING\n"
1530 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1531 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1532 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1533 "#endif\n"
1534 "\n"
1535 "\n"
1536 "\n"
1537 "\n"
1538 "#ifdef MODE_LIGHTMAP\n"
1539 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1540 "#endif // MODE_LIGHTMAP\n"
1541 "#ifdef MODE_VERTEXCOLOR\n"
1542 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1543 "#endif // MODE_VERTEXCOLOR\n"
1544 "#ifdef MODE_FLATCOLOR\n"
1545 "       color.rgb = diffusetex * Color_Ambient;\n"
1546 "#endif // MODE_FLATCOLOR\n"
1547 "\n"
1548 "\n"
1549 "\n"
1550 "\n"
1551 "#ifdef SHADING\n"
1552 "# ifdef USEDIFFUSE\n"
1553 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1554 "#  ifdef USESPECULAR\n"
1555 "#   ifdef USEEXACTSPECULARMATH\n"
1556 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1557 "#   else\n"
1558 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1559 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1560 "#   endif\n"
1561 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1562 "#  else\n"
1563 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1564 "#  endif\n"
1565 "# else\n"
1566 "       color.rgb = diffusetex * Color_Ambient;\n"
1567 "# endif\n"
1568 "#endif\n"
1569 "\n"
1570 "#ifdef USEDEFERREDLIGHTMAP\n"
1571 "       color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1572 "       color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1573 "#endif\n"
1574 "\n"
1575 "#ifdef USEGLOW\n"
1576 "#ifdef USEVERTEXTEXTUREBLEND\n"
1577 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1578 "#else\n"
1579 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1580 "#endif\n"
1581 "#endif\n"
1582 "\n"
1583 "#ifdef USEFOG\n"
1584 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1585 "#endif\n"
1586 "\n"
1587 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1588 "#ifdef USEREFLECTION\n"
1589 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1590 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1591 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1592 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1593 "       // FIXME temporary hack to detect the case that the reflection\n"
1594 "       // gets blackened at edges due to leaving the area that contains actual\n"
1595 "       // content.\n"
1596 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1597 "       // 'appening.\n"
1598 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1599 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1600 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1601 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1602 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1603 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1604 "#endif\n"
1605 "\n"
1606 "       gl_FragColor = vec4(color);\n"
1607 "}\n"
1608 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1609 "#endif // !MODE_DEFERREDGEOMETRY\n"
1610 "\n"
1611 "#endif // FRAGMENT_SHADER\n"
1612 "\n"
1613 "#endif // !MODE_WATER\n"
1614 "#endif // !MODE_REFRACTION\n"
1615 "#endif // !MODE_BLOOMBLUR\n"
1616 "#endif // !MODE_GENERIC\n"
1617 "#endif // !MODE_POSTPROCESS\n"
1618 "#endif // !MODE_SHOWDEPTH\n"
1619 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1620 ;
1621
1622 typedef struct shaderpermutationinfo_s
1623 {
1624         const char *pretext;
1625         const char *name;
1626 }
1627 shaderpermutationinfo_t;
1628
1629 typedef struct shadermodeinfo_s
1630 {
1631         const char *vertexfilename;
1632         const char *geometryfilename;
1633         const char *fragmentfilename;
1634         const char *pretext;
1635         const char *name;
1636 }
1637 shadermodeinfo_t;
1638
1639 typedef enum shaderpermutation_e
1640 {
1641         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1642         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1643         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1644         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1645         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1646         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1647         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1648         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1649         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1650         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1651         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1652         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1653         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1654         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1655         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1656         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1657         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1658         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1659         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1660         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1661         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1662         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1663         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1664         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1665         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1666         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
1667         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
1668         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
1669 }
1670 shaderpermutation_t;
1671
1672 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1673 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1674 {
1675         {"#define USEDIFFUSE\n", " diffuse"},
1676         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1677         {"#define USEVIEWTINT\n", " viewtint"},
1678         {"#define USECOLORMAPPING\n", " colormapping"},
1679         {"#define USESATURATION\n", " saturation"},
1680         {"#define USEFOGINSIDE\n", " foginside"},
1681         {"#define USEFOGOUTSIDE\n", " fogoutside"},
1682         {"#define USEGAMMARAMPS\n", " gammaramps"},
1683         {"#define USECUBEFILTER\n", " cubefilter"},
1684         {"#define USEGLOW\n", " glow"},
1685         {"#define USEBLOOM\n", " bloom"},
1686         {"#define USESPECULAR\n", " specular"},
1687         {"#define USEPOSTPROCESSING\n", " postprocessing"},
1688         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1689         {"#define USEREFLECTION\n", " reflection"},
1690         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1691         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1692         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1693         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1694         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1695         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1696         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1697         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1698         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1699         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1700         {"#define USEALPHAKILL\n", " alphakill"},
1701 };
1702
1703 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1704 typedef enum shadermode_e
1705 {
1706         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1707         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1708         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1709         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1710         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1711         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1712         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1713         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1714         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1715         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1716         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1717         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1718         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1719         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1720         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1721         SHADERMODE_COUNT
1722 }
1723 shadermode_t;
1724
1725 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1726 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1727 {
1728         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1729         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1730         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1731         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1732         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1733         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1734         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1735         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1736         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1737         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1738         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1739         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1740         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1741         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1742         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1743 };
1744
1745 struct r_glsl_permutation_s;
1746 typedef struct r_glsl_permutation_s
1747 {
1748         /// hash lookup data
1749         struct r_glsl_permutation_s *hashnext;
1750         unsigned int mode;
1751         unsigned int permutation;
1752
1753         /// indicates if we have tried compiling this permutation already
1754         qboolean compiled;
1755         /// 0 if compilation failed
1756         int program;
1757         /// locations of detected uniforms in program object, or -1 if not found
1758         int loc_Texture_First;
1759         int loc_Texture_Second;
1760         int loc_Texture_GammaRamps;
1761         int loc_Texture_Normal;
1762         int loc_Texture_Color;
1763         int loc_Texture_Gloss;
1764         int loc_Texture_Glow;
1765         int loc_Texture_SecondaryNormal;
1766         int loc_Texture_SecondaryColor;
1767         int loc_Texture_SecondaryGloss;
1768         int loc_Texture_SecondaryGlow;
1769         int loc_Texture_Pants;
1770         int loc_Texture_Shirt;
1771         int loc_Texture_FogMask;
1772         int loc_Texture_Lightmap;
1773         int loc_Texture_Deluxemap;
1774         int loc_Texture_Attenuation;
1775         int loc_Texture_Cube;
1776         int loc_Texture_Refraction;
1777         int loc_Texture_Reflection;
1778         int loc_Texture_ShadowMapRect;
1779         int loc_Texture_ShadowMapCube;
1780         int loc_Texture_ShadowMap2D;
1781         int loc_Texture_CubeProjection;
1782         int loc_Texture_ScreenDepth;
1783         int loc_Texture_ScreenNormalMap;
1784         int loc_Texture_ScreenDiffuse;
1785         int loc_Texture_ScreenSpecular;
1786         int loc_Alpha;
1787         int loc_BloomBlur_Parameters;
1788         int loc_ClientTime;
1789         int loc_Color_Ambient;
1790         int loc_Color_Diffuse;
1791         int loc_Color_Specular;
1792         int loc_Color_Glow;
1793         int loc_Color_Pants;
1794         int loc_Color_Shirt;
1795         int loc_DeferredColor_Ambient;
1796         int loc_DeferredColor_Diffuse;
1797         int loc_DeferredColor_Specular;
1798         int loc_DeferredMod_Diffuse;
1799         int loc_DeferredMod_Specular;
1800         int loc_DistortScaleRefractReflect;
1801         int loc_EyePosition;
1802         int loc_FogColor;
1803         int loc_FogHeightFade;
1804         int loc_FogPlane;
1805         int loc_FogPlaneViewDist;
1806         int loc_FogRangeRecip;
1807         int loc_LightColor;
1808         int loc_LightDir;
1809         int loc_LightPosition;
1810         int loc_OffsetMapping_Scale;
1811         int loc_PixelSize;
1812         int loc_ReflectColor;
1813         int loc_ReflectFactor;
1814         int loc_ReflectOffset;
1815         int loc_RefractColor;
1816         int loc_Saturation;
1817         int loc_ScreenCenterRefractReflect;
1818         int loc_ScreenScaleRefractReflect;
1819         int loc_ScreenToDepth;
1820         int loc_ShadowMap_Parameters;
1821         int loc_ShadowMap_TextureScale;
1822         int loc_SpecularPower;
1823         int loc_UserVec1;
1824         int loc_UserVec2;
1825         int loc_UserVec3;
1826         int loc_UserVec4;
1827         int loc_ViewTintColor;
1828         int loc_ViewToLight;
1829         int loc_ModelToLight;
1830         int loc_TexMatrix;
1831         int loc_BackgroundTexMatrix;
1832 }
1833 r_glsl_permutation_t;
1834
1835 #define SHADERPERMUTATION_HASHSIZE 256
1836
1837 /// information about each possible shader permutation
1838 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1839 /// currently selected permutation
1840 r_glsl_permutation_t *r_glsl_permutation;
1841 /// storage for permutations linked in the hash table
1842 memexpandablearray_t r_glsl_permutationarray;
1843
1844 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1845 {
1846         //unsigned int hashdepth = 0;
1847         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1848         r_glsl_permutation_t *p;
1849         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1850         {
1851                 if (p->mode == mode && p->permutation == permutation)
1852                 {
1853                         //if (hashdepth > 10)
1854                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1855                         return p;
1856                 }
1857                 //hashdepth++;
1858         }
1859         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1860         p->mode = mode;
1861         p->permutation = permutation;
1862         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1863         r_glsl_permutationhash[mode][hashindex] = p;
1864         //if (hashdepth > 10)
1865         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1866         return p;
1867 }
1868
1869 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1870 {
1871         char *shaderstring;
1872         if (!filename || !filename[0])
1873                 return NULL;
1874         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1875         if (shaderstring)
1876         {
1877                 if (printfromdisknotice)
1878                         Con_DPrintf("from disk %s... ", filename);
1879                 return shaderstring;
1880         }
1881         else if (!strcmp(filename, "glsl/default.glsl"))
1882         {
1883                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1884                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1885         }
1886         return shaderstring;
1887 }
1888
1889 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1890 {
1891         int i;
1892         shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1893         int vertstrings_count = 0;
1894         int geomstrings_count = 0;
1895         int fragstrings_count = 0;
1896         char *vertexstring, *geometrystring, *fragmentstring;
1897         const char *vertstrings_list[32+3];
1898         const char *geomstrings_list[32+3];
1899         const char *fragstrings_list[32+3];
1900         char permutationname[256];
1901
1902         if (p->compiled)
1903                 return;
1904         p->compiled = true;
1905         p->program = 0;
1906
1907         permutationname[0] = 0;
1908         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1909         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1910         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1911
1912         strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1913
1914         // the first pretext is which type of shader to compile as
1915         // (later these will all be bound together as a program object)
1916         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1917         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1918         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1919
1920         // the second pretext is the mode (for example a light source)
1921         vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1922         geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1923         fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1924         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1925
1926         // now add all the permutation pretexts
1927         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1928         {
1929                 if (permutation & (1<<i))
1930                 {
1931                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1932                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1933                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1934                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1935                 }
1936                 else
1937                 {
1938                         // keep line numbers correct
1939                         vertstrings_list[vertstrings_count++] = "\n";
1940                         geomstrings_list[geomstrings_count++] = "\n";
1941                         fragstrings_list[fragstrings_count++] = "\n";
1942                 }
1943         }
1944
1945         // now append the shader text itself
1946         vertstrings_list[vertstrings_count++] = vertexstring;
1947         geomstrings_list[geomstrings_count++] = geometrystring;
1948         fragstrings_list[fragstrings_count++] = fragmentstring;
1949
1950         // if any sources were NULL, clear the respective list
1951         if (!vertexstring)
1952                 vertstrings_count = 0;
1953         if (!geometrystring)
1954                 geomstrings_count = 0;
1955         if (!fragmentstring)
1956                 fragstrings_count = 0;
1957
1958         // compile the shader program
1959         if (vertstrings_count + geomstrings_count + fragstrings_count)
1960                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1961         if (p->program)
1962         {
1963                 CHECKGLERROR
1964                 qglUseProgramObjectARB(p->program);CHECKGLERROR
1965                 // look up all the uniform variable names we care about, so we don't
1966                 // have to look them up every time we set them
1967
1968                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
1969                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
1970                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1971                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
1972                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
1973                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1974                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
1975                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1976                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1977                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1978                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1979                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
1980                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1981                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1982                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1983                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1984                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1985                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
1986                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1987                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1988                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1989                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1990                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1991                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1992                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
1993                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
1994                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
1995                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
1996                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
1997                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
1998                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
1999                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
2000                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
2001                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
2002                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
2003                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
2004                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
2005                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
2006                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
2007                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
2008                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
2009                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
2010                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
2011                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
2012                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
2013                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
2014                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
2015                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
2016                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
2017                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
2018                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
2019                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
2020                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
2021                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
2022                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
2023                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
2024                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
2025                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
2026                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
2027                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
2028                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2029                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2030                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2031                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2032                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
2033                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
2034                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
2035                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
2036                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
2037                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
2038                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
2039                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
2040                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
2041                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
2042                 // initialize the samplers to refer to the texture units we use
2043                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
2044                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
2045                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
2046                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
2047                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
2048                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
2049                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
2050                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2051                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2052                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2053                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
2054                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
2055                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
2056                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
2057                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
2058                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
2059                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
2060                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
2061                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
2062                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
2063                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
2064                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
2065                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
2066                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2067                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
2068                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2069                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
2070                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2071                 CHECKGLERROR
2072                 if (developer.integer)
2073                         Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2074         }
2075         else
2076                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
2077
2078         // free the strings
2079         if (vertexstring)
2080                 Mem_Free(vertexstring);
2081         if (geometrystring)
2082                 Mem_Free(geometrystring);
2083         if (fragmentstring)
2084                 Mem_Free(fragmentstring);
2085 }
2086
2087 void R_GLSL_Restart_f(void)
2088 {
2089         unsigned int i, limit;
2090         r_glsl_permutation_t *p;
2091         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2092         for (i = 0;i < limit;i++)
2093         {
2094                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2095                 {
2096                         GL_Backend_FreeProgram(p->program);
2097                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2098                 }
2099         }
2100         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2101 }
2102
2103 void R_GLSL_DumpShader_f(void)
2104 {
2105         int i;
2106
2107         qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2108         if(!file)
2109         {
2110                 Con_Printf("failed to write to glsl/default.glsl\n");
2111                 return;
2112         }
2113
2114         FS_Print(file, "/* The engine may define the following macros:\n");
2115         FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2116         for (i = 0;i < SHADERMODE_COUNT;i++)
2117                 FS_Print(file, shadermodeinfo[i].pretext);
2118         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2119                 FS_Print(file, shaderpermutationinfo[i].pretext);
2120         FS_Print(file, "*/\n");
2121         FS_Print(file, builtinshaderstring);
2122         FS_Close(file);
2123
2124         Con_Printf("glsl/default.glsl written\n");
2125 }
2126
2127 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
2128 {
2129         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2130         if (r_glsl_permutation != perm)
2131         {
2132                 r_glsl_permutation = perm;
2133                 if (!r_glsl_permutation->program)
2134                 {
2135                         if (!r_glsl_permutation->compiled)
2136                                 R_GLSL_CompilePermutation(perm, mode, permutation);
2137                         if (!r_glsl_permutation->program)
2138                         {
2139                                 // remove features until we find a valid permutation
2140                                 int i;
2141                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2142                                 {
2143                                         // reduce i more quickly whenever it would not remove any bits
2144                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2145                                         if (!(permutation & j))
2146                                                 continue;
2147                                         permutation -= j;
2148                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2149                                         if (!r_glsl_permutation->compiled)
2150                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
2151                                         if (r_glsl_permutation->program)
2152                                                 break;
2153                                 }
2154                                 if (i >= SHADERPERMUTATION_COUNT)
2155                                 {
2156                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2157                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2158                                         qglUseProgramObjectARB(0);CHECKGLERROR
2159                                         return; // no bit left to clear, entire mode is broken
2160                                 }
2161                         }
2162                 }
2163                 CHECKGLERROR
2164                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2165         }
2166 }
2167
2168 void R_SetupGenericShader(qboolean usetexture)
2169 {
2170         switch(vid.renderpath)
2171         {
2172         case RENDERPATH_GL20:
2173                 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2174                 break;
2175         case RENDERPATH_GL13:
2176         case RENDERPATH_GL11:
2177                 break;
2178         }
2179 }
2180
2181 void R_SetupGenericTwoTextureShader(int texturemode)
2182 {
2183         switch (vid.renderpath)
2184         {
2185         case RENDERPATH_GL20:
2186                 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
2187                 break;
2188         case RENDERPATH_GL13:
2189         case RENDERPATH_GL11:
2190                 R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
2191                 break;
2192         }
2193 }
2194
2195 void R_SetupDepthOrShadowShader(void)
2196 {
2197         switch (vid.renderpath)
2198         {
2199         case RENDERPATH_GL20:
2200                 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2201                 break;
2202         case RENDERPATH_GL13:
2203                 break;
2204         case RENDERPATH_GL11:
2205                 break;
2206         }
2207 }
2208
2209 void R_SetupShowDepthShader(void)
2210 {
2211         switch (vid.renderpath)
2212         {
2213         case RENDERPATH_GL20:
2214                 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2215                 break;
2216         case RENDERPATH_GL13:
2217                 break;
2218         case RENDERPATH_GL11:
2219                 break;
2220         }
2221 }
2222
2223 extern qboolean r_shadow_usingdeferredprepass;
2224 extern cvar_t r_shadow_deferred_8bitrange;
2225 extern rtexture_t *r_shadow_attenuationgradienttexture;
2226 extern rtexture_t *r_shadow_attenuation2dtexture;
2227 extern rtexture_t *r_shadow_attenuation3dtexture;
2228 extern qboolean r_shadow_usingshadowmaprect;
2229 extern qboolean r_shadow_usingshadowmapcube;
2230 extern qboolean r_shadow_usingshadowmap2d;
2231 extern float r_shadow_shadowmap_texturescale[2];
2232 extern float r_shadow_shadowmap_parameters[4];
2233 extern qboolean r_shadow_shadowmapvsdct;
2234 extern qboolean r_shadow_shadowmapsampler;
2235 extern int r_shadow_shadowmappcf;
2236 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2237 {
2238         // select a permutation of the lighting shader appropriate to this
2239         // combination of texture, entity, light source, and fogging, only use the
2240         // minimum features necessary to avoid wasting rendering time in the
2241         // fragment shader on features that are not being used
2242         unsigned int permutation = 0;
2243         unsigned int mode = 0;
2244         float m16f[16];
2245         // TODO: implement geometry-shader based shadow volumes someday
2246         if (r_glsl_offsetmapping.integer)
2247         {
2248                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2249                 if (r_glsl_offsetmapping_reliefmapping.integer)
2250                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2251         }
2252         if (rsurfacepass == RSURFPASS_BACKGROUND)
2253         {
2254                 // distorted background
2255                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2256                         mode = SHADERMODE_WATER;
2257                 else
2258                         mode = SHADERMODE_REFRACTION;
2259         }
2260         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2261         {
2262                 // normalmap (deferred prepass), may use alpha test on diffuse
2263                 mode = SHADERMODE_DEFERREDGEOMETRY;
2264                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2265                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2266                 if (r_glsl_offsetmapping.integer)
2267                 {
2268                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2269                         if (r_glsl_offsetmapping_reliefmapping.integer)
2270                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2271                 }
2272         }
2273         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2274         {
2275                 // light source
2276                 mode = SHADERMODE_LIGHTSOURCE;
2277                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2278                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2279                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2280                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2281                 if (diffusescale > 0)
2282                         permutation |= SHADERPERMUTATION_DIFFUSE;
2283                 if (specularscale > 0)
2284                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2285                 if (r_refdef.fogenabled)
2286                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2287                 if (rsurface.texture->colormapping)
2288                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2289                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2290                 {
2291                         if (r_shadow_usingshadowmaprect)
2292                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2293                         if (r_shadow_usingshadowmap2d)
2294                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2295                         if (r_shadow_usingshadowmapcube)
2296                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2297                         else if(r_shadow_shadowmapvsdct)
2298                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2299
2300                         if (r_shadow_shadowmapsampler)
2301                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2302                         if (r_shadow_shadowmappcf > 1)
2303                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2304                         else if (r_shadow_shadowmappcf)
2305                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2306                 }
2307         }
2308         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2309         {
2310                 // unshaded geometry (fullbright or ambient model lighting)
2311                 mode = SHADERMODE_FLATCOLOR;
2312                 ambientscale = diffusescale = specularscale = 0;
2313                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2314                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2315                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2316                         permutation |= SHADERPERMUTATION_GLOW;
2317                 if (r_refdef.fogenabled)
2318                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2319                 if (rsurface.texture->colormapping)
2320                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2321                 if (r_glsl_offsetmapping.integer)
2322                 {
2323                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2324                         if (r_glsl_offsetmapping_reliefmapping.integer)
2325                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2326                 }
2327                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2328                         permutation |= SHADERPERMUTATION_REFLECTION;
2329         }
2330         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2331         {
2332                 // directional model lighting
2333                 mode = SHADERMODE_LIGHTDIRECTION;
2334                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2335                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2336                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2337                         permutation |= SHADERPERMUTATION_GLOW;
2338                 permutation |= SHADERPERMUTATION_DIFFUSE;
2339                 if (specularscale > 0)
2340                         permutation |= SHADERPERMUTATION_SPECULAR;
2341                 if (r_refdef.fogenabled)
2342                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2343                 if (rsurface.texture->colormapping)
2344                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2345                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2346                         permutation |= SHADERPERMUTATION_REFLECTION;
2347                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2348                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2349         }
2350         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2351         {
2352                 // ambient model lighting
2353                 mode = SHADERMODE_LIGHTDIRECTION;
2354                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2355                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2356                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2357                         permutation |= SHADERPERMUTATION_GLOW;
2358                 if (r_refdef.fogenabled)
2359                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2360                 if (rsurface.texture->colormapping)
2361                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2362                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2363                         permutation |= SHADERPERMUTATION_REFLECTION;
2364                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2365                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2366         }
2367         else
2368         {
2369                 // lightmapped wall
2370                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2371                 {
2372                         // deluxemapping (light direction texture)
2373                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2374                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2375                         else
2376                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2377                         permutation |= SHADERPERMUTATION_DIFFUSE;
2378                         if (specularscale > 0)
2379                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2380                 }
2381                 else if (r_glsl_deluxemapping.integer >= 2)
2382                 {
2383                         // fake deluxemapping (uniform light direction in tangentspace)
2384                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2385                         permutation |= SHADERPERMUTATION_DIFFUSE;
2386                         if (specularscale > 0)
2387                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2388                 }
2389                 else if (rsurface.uselightmaptexture)
2390                 {
2391                         // ordinary lightmapping (q1bsp, q3bsp)
2392                         mode = SHADERMODE_LIGHTMAP;
2393                 }
2394                 else
2395                 {
2396                         // ordinary vertex coloring (q3bsp)
2397                         mode = SHADERMODE_VERTEXCOLOR;
2398                 }
2399                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2400                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2401                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2402                         permutation |= SHADERPERMUTATION_GLOW;
2403                 if (r_refdef.fogenabled)
2404                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2405                 if (rsurface.texture->colormapping)
2406                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2407                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2408                         permutation |= SHADERPERMUTATION_REFLECTION;
2409                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2410                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2411         }
2412         if(permutation & SHADERPERMUTATION_SPECULAR)
2413                 if(r_shadow_glossexact.integer)
2414                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2415         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
2416                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2417         R_SetupShader_SetPermutation(mode, permutation);
2418         if (mode == SHADERMODE_LIGHTSOURCE)
2419         {
2420                 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2421                 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2422                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2423                 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);
2424                 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);
2425                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
2426
2427                 // additive passes are only darkened by fog, not tinted
2428                 if (r_glsl_permutation->loc_FogColor >= 0)
2429                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2430                 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]);
2431                 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]);
2432                 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2433         }
2434         else
2435         {
2436                 if (mode == SHADERMODE_FLATCOLOR)
2437                 {
2438                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
2439                 }
2440                 else if (mode == SHADERMODE_LIGHTDIRECTION)
2441                 {
2442                         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]);
2443                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
2444                         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);
2445                         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);
2446                         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);
2447                         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]);
2448                         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]);
2449                 }
2450                 else
2451                 {
2452                         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]);
2453                         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]);
2454                         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);
2455                         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);
2456                         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);
2457                 }
2458                 // additive passes are only darkened by fog, not tinted
2459                 if (r_glsl_permutation->loc_FogColor >= 0)
2460                 {
2461                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2462                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2463                         else
2464                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2465                 }
2466                 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);
2467                 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]);
2468                 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]);
2469                 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2470                 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2471                 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2472                 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2473                 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2474         }
2475         if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2476         if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2477         if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2478         if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
2479         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2480         if (r_glsl_permutation->loc_Color_Pants >= 0)
2481         {
2482                 if (rsurface.texture->currentskinframe->pants)
2483                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2484                 else
2485                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2486         }
2487         if (r_glsl_permutation->loc_Color_Shirt >= 0)
2488         {
2489                 if (rsurface.texture->currentskinframe->shirt)
2490                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2491                 else
2492                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2493         }
2494         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]);
2495         if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2496         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2497         if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2498         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2499         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]);
2500         CHECKGLERROR
2501 }
2502
2503 void R_SetupDeferredLightShader(const rtlight_t *rtlight)
2504 {
2505         // select a permutation of the lighting shader appropriate to this
2506         // combination of texture, entity, light source, and fogging, only use the
2507         // minimum features necessary to avoid wasting rendering time in the
2508         // fragment shader on features that are not being used
2509         unsigned int permutation = 0;
2510         unsigned int mode = 0;
2511         const float *lightcolorbase = rtlight->currentcolor;
2512         float ambientscale = rtlight->ambientscale;
2513         float diffusescale = rtlight->diffusescale;
2514         float specularscale = rtlight->specularscale;
2515         // this is the location of the light in view space
2516         vec3_t viewlightorigin;
2517         // this transforms from view space (camera) to light space (cubemap)
2518         matrix4x4_t viewtolight;
2519         matrix4x4_t lighttoview;
2520         float viewtolight16f[16];
2521         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2522         // light source
2523         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2524         if (rtlight->currentcubemap != r_texture_whitecube)
2525                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2526         if (diffusescale > 0)
2527                 permutation |= SHADERPERMUTATION_DIFFUSE;
2528         if (specularscale > 0)
2529         {
2530                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2531                 if (r_shadow_glossexact.integer)
2532                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2533         }
2534         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2535         {
2536                 if (r_shadow_usingshadowmaprect)
2537                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2538                 if (r_shadow_usingshadowmap2d)
2539                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2540                 if (r_shadow_usingshadowmapcube)
2541                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2542                 else if(r_shadow_shadowmapvsdct)
2543                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2544
2545                 if (r_shadow_shadowmapsampler)
2546                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2547                 if (r_shadow_shadowmappcf > 1)
2548                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2549                 else if (r_shadow_shadowmappcf)
2550                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2551         }
2552         R_SetupShader_SetPermutation(mode, permutation);
2553         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2554         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2555         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2556         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2557         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2558         if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight, 1, false, viewtolight16f);
2559         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);
2560         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);
2561         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);
2562         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]);
2563         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]);
2564         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));
2565         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]);
2566 }
2567
2568 #define SKINFRAME_HASH 1024
2569
2570 typedef struct
2571 {
2572         int loadsequence; // incremented each level change
2573         memexpandablearray_t array;
2574         skinframe_t *hash[SKINFRAME_HASH];
2575 }
2576 r_skinframe_t;
2577 r_skinframe_t r_skinframe;
2578
2579 void R_SkinFrame_PrepareForPurge(void)
2580 {
2581         r_skinframe.loadsequence++;
2582         // wrap it without hitting zero
2583         if (r_skinframe.loadsequence >= 200)
2584                 r_skinframe.loadsequence = 1;
2585 }
2586
2587 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2588 {
2589         if (!skinframe)
2590                 return;
2591         // mark the skinframe as used for the purging code
2592         skinframe->loadsequence = r_skinframe.loadsequence;
2593 }
2594
2595 void R_SkinFrame_Purge(void)
2596 {
2597         int i;
2598         skinframe_t *s;
2599         for (i = 0;i < SKINFRAME_HASH;i++)
2600         {
2601                 for (s = r_skinframe.hash[i];s;s = s->next)
2602                 {
2603                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2604                         {
2605                                 if (s->merged == s->base)
2606                                         s->merged = NULL;
2607                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2608                                 R_PurgeTexture(s->stain );s->stain  = NULL;
2609                                 R_PurgeTexture(s->merged);s->merged = NULL;
2610                                 R_PurgeTexture(s->base  );s->base   = NULL;
2611                                 R_PurgeTexture(s->pants );s->pants  = NULL;
2612                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
2613                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
2614                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
2615                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
2616                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
2617                                 s->loadsequence = 0;
2618                         }
2619                 }
2620         }
2621 }
2622
2623 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2624         skinframe_t *item;
2625         char basename[MAX_QPATH];
2626
2627         Image_StripImageExtension(name, basename, sizeof(basename));
2628
2629         if( last == NULL ) {
2630                 int hashindex;
2631                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2632                 item = r_skinframe.hash[hashindex];
2633         } else {
2634                 item = last->next;
2635         }
2636
2637         // linearly search through the hash bucket
2638         for( ; item ; item = item->next ) {
2639                 if( !strcmp( item->basename, basename ) ) {
2640                         return item;
2641                 }
2642         }
2643         return NULL;
2644 }
2645
2646 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2647 {
2648         skinframe_t *item;
2649         int hashindex;
2650         char basename[MAX_QPATH];
2651
2652         Image_StripImageExtension(name, basename, sizeof(basename));
2653
2654         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2655         for (item = r_skinframe.hash[hashindex];item;item = item->next)
2656                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2657                         break;
2658
2659         if (!item) {
2660                 rtexture_t *dyntexture;
2661                 // check whether its a dynamic texture
2662                 dyntexture = CL_GetDynTexture( basename );
2663                 if (!add && !dyntexture)
2664                         return NULL;
2665                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2666                 memset(item, 0, sizeof(*item));
2667                 strlcpy(item->basename, basename, sizeof(item->basename));
2668                 item->base = dyntexture; // either NULL or dyntexture handle
2669                 item->textureflags = textureflags;
2670                 item->comparewidth = comparewidth;
2671                 item->compareheight = compareheight;
2672                 item->comparecrc = comparecrc;
2673                 item->next = r_skinframe.hash[hashindex];
2674                 r_skinframe.hash[hashindex] = item;
2675         }
2676         else if( item->base == NULL )
2677         {
2678                 rtexture_t *dyntexture;
2679                 // check whether its a dynamic texture
2680                 // 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]
2681                 dyntexture = CL_GetDynTexture( basename );
2682                 item->base = dyntexture; // either NULL or dyntexture handle
2683         }
2684
2685         R_SkinFrame_MarkUsed(item);
2686         return item;
2687 }
2688
2689 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2690         { \
2691                 unsigned long long avgcolor[5], wsum; \
2692                 int pix, comp, w; \
2693                 avgcolor[0] = 0; \
2694                 avgcolor[1] = 0; \
2695                 avgcolor[2] = 0; \
2696                 avgcolor[3] = 0; \
2697                 avgcolor[4] = 0; \
2698                 wsum = 0; \
2699                 for(pix = 0; pix < cnt; ++pix) \
2700                 { \
2701                         w = 0; \
2702                         for(comp = 0; comp < 3; ++comp) \
2703                                 w += getpixel; \
2704                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2705                         { \
2706                                 ++wsum; \
2707                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2708                                 w = getpixel; \
2709                                 for(comp = 0; comp < 3; ++comp) \
2710                                         avgcolor[comp] += getpixel * w; \
2711                                 avgcolor[3] += w; \
2712                         } \
2713                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2714                         avgcolor[4] += getpixel; \
2715                 } \
2716                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2717                         avgcolor[3] = 1; \
2718                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2719                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2720                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2721                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2722         }
2723
2724 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2725 {
2726         int j;
2727         unsigned char *pixels;
2728         unsigned char *bumppixels;
2729         unsigned char *basepixels = NULL;
2730         int basepixels_width;
2731         int basepixels_height;
2732         skinframe_t *skinframe;
2733
2734         if (cls.state == ca_dedicated)
2735                 return NULL;
2736
2737         // return an existing skinframe if already loaded
2738         // if loading of the first image fails, don't make a new skinframe as it
2739         // would cause all future lookups of this to be missing
2740         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2741         if (skinframe && skinframe->base)
2742                 return skinframe;
2743
2744         basepixels = loadimagepixelsbgra(name, complain, true);
2745         if (basepixels == NULL)
2746                 return NULL;
2747
2748         if (developer_loading.integer)
2749                 Con_Printf("loading skin \"%s\"\n", name);
2750
2751         // we've got some pixels to store, so really allocate this new texture now
2752         if (!skinframe)
2753                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2754         skinframe->stain = NULL;
2755         skinframe->merged = NULL;
2756         skinframe->base = r_texture_notexture;
2757         skinframe->pants = NULL;
2758         skinframe->shirt = NULL;
2759         skinframe->nmap = r_texture_blanknormalmap;
2760         skinframe->gloss = NULL;
2761         skinframe->glow = NULL;
2762         skinframe->fog = NULL;
2763         skinframe->hasalpha = false;
2764
2765         basepixels_width = image_width;
2766         basepixels_height = image_height;
2767         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);
2768
2769         if (textureflags & TEXF_ALPHA)
2770         {
2771                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2772                 {
2773                         if (basepixels[j] < 255)
2774                         {
2775                                 skinframe->hasalpha = true;
2776                                 break;
2777                         }
2778                 }
2779                 if (r_loadfog && skinframe->hasalpha)
2780                 {
2781                         // has transparent pixels
2782                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2783                         for (j = 0;j < image_width * image_height * 4;j += 4)
2784                         {
2785                                 pixels[j+0] = 255;
2786                                 pixels[j+1] = 255;
2787                                 pixels[j+2] = 255;
2788                                 pixels[j+3] = basepixels[j+3];
2789                         }
2790                         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);
2791                         Mem_Free(pixels);
2792                 }
2793         }
2794
2795         R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2796         //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]);
2797
2798         // _norm is the name used by tenebrae and has been adopted as standard
2799         if (r_loadnormalmap)
2800         {
2801                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2802                 {
2803                         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);
2804                         Mem_Free(pixels);
2805                         pixels = NULL;
2806                 }
2807                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2808                 {
2809                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2810                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2811                         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);
2812                         Mem_Free(pixels);
2813                         Mem_Free(bumppixels);
2814                 }
2815                 else if (r_shadow_bumpscale_basetexture.value > 0)
2816                 {
2817                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2818                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2819                         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);
2820                         Mem_Free(pixels);
2821                 }
2822         }
2823         // _luma is supported for tenebrae compatibility
2824         // (I think it's a very stupid name, but oh well)
2825         // _glow is the preferred name
2826         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;}
2827         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;}
2828         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;}
2829         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;}
2830
2831         if (basepixels)
2832                 Mem_Free(basepixels);
2833
2834         return skinframe;
2835 }
2836
2837 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2838 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2839 {
2840         int i;
2841         unsigned char *temp1, *temp2;
2842         skinframe_t *skinframe;
2843
2844         if (cls.state == ca_dedicated)
2845                 return NULL;
2846
2847         // if already loaded just return it, otherwise make a new skinframe
2848         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2849         if (skinframe && skinframe->base)
2850                 return skinframe;
2851
2852         skinframe->stain = NULL;
2853         skinframe->merged = NULL;
2854         skinframe->base = r_texture_notexture;
2855         skinframe->pants = NULL;
2856         skinframe->shirt = NULL;
2857         skinframe->nmap = r_texture_blanknormalmap;
2858         skinframe->gloss = NULL;
2859         skinframe->glow = NULL;
2860         skinframe->fog = NULL;
2861         skinframe->hasalpha = false;
2862
2863         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2864         if (!skindata)
2865                 return NULL;
2866
2867         if (developer_loading.integer)
2868                 Con_Printf("loading 32bit skin \"%s\"\n", name);
2869
2870         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2871         {
2872                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2873                 temp2 = temp1 + width * height * 4;
2874                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2875                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2876                 Mem_Free(temp1);
2877         }
2878         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2879         if (textureflags & TEXF_ALPHA)
2880         {
2881                 for (i = 3;i < width * height * 4;i += 4)
2882                 {
2883                         if (skindata[i] < 255)
2884                         {
2885                                 skinframe->hasalpha = true;
2886                                 break;
2887                         }
2888                 }
2889                 if (r_loadfog && skinframe->hasalpha)
2890                 {
2891                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2892                         memcpy(fogpixels, skindata, width * height * 4);
2893                         for (i = 0;i < width * height * 4;i += 4)
2894                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2895                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2896                         Mem_Free(fogpixels);
2897                 }
2898         }
2899
2900         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2901         //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]);
2902
2903         return skinframe;
2904 }
2905
2906 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2907 {
2908         int i;
2909         int featuresmask;
2910         skinframe_t *skinframe;
2911
2912         if (cls.state == ca_dedicated)
2913                 return NULL;
2914
2915         // if already loaded just return it, otherwise make a new skinframe
2916         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2917         if (skinframe && skinframe->base)
2918                 return skinframe;
2919
2920         skinframe->stain = NULL;
2921         skinframe->merged = NULL;
2922         skinframe->base = r_texture_notexture;
2923         skinframe->pants = NULL;
2924         skinframe->shirt = NULL;
2925         skinframe->nmap = r_texture_blanknormalmap;
2926         skinframe->gloss = NULL;
2927         skinframe->glow = NULL;
2928         skinframe->fog = NULL;
2929         skinframe->hasalpha = false;
2930
2931         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2932         if (!skindata)
2933                 return NULL;
2934
2935         if (developer_loading.integer)
2936                 Con_Printf("loading quake skin \"%s\"\n", name);
2937
2938         // 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)
2939         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
2940         memcpy(skinframe->qpixels, skindata, width*height);
2941         skinframe->qwidth = width;
2942         skinframe->qheight = height;
2943
2944         featuresmask = 0;
2945         for (i = 0;i < width * height;i++)
2946                 featuresmask |= palette_featureflags[skindata[i]];
2947
2948         skinframe->hasalpha = false;
2949         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2950         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2951         skinframe->qgeneratemerged = true;
2952         skinframe->qgeneratebase = skinframe->qhascolormapping;
2953         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2954
2955         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2956         //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]);
2957
2958         return skinframe;
2959 }
2960
2961 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2962 {
2963         int width;
2964         int height;
2965         unsigned char *skindata;
2966
2967         if (!skinframe->qpixels)
2968                 return;
2969
2970         if (!skinframe->qhascolormapping)
2971                 colormapped = false;
2972
2973         if (colormapped)
2974         {
2975                 if (!skinframe->qgeneratebase)
2976                         return;
2977         }
2978         else
2979         {
2980                 if (!skinframe->qgeneratemerged)
2981                         return;
2982         }
2983
2984         width = skinframe->qwidth;
2985         height = skinframe->qheight;
2986         skindata = skinframe->qpixels;
2987
2988         if (skinframe->qgeneratenmap)
2989         {
2990                 unsigned char *temp1, *temp2;
2991                 skinframe->qgeneratenmap = false;
2992                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2993                 temp2 = temp1 + width * height * 4;
2994                 // use either a custom palette or the quake palette
2995                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2996                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2997                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2998                 Mem_Free(temp1);
2999         }
3000
3001         if (skinframe->qgenerateglow)
3002         {
3003                 skinframe->qgenerateglow = false;
3004                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
3005         }
3006
3007         if (colormapped)
3008         {
3009                 skinframe->qgeneratebase = false;
3010                 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);
3011                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
3012                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
3013         }
3014         else
3015         {
3016                 skinframe->qgeneratemerged = false;
3017                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3018         }
3019
3020         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3021         {
3022                 Mem_Free(skinframe->qpixels);
3023                 skinframe->qpixels = NULL;
3024         }
3025 }
3026
3027 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)
3028 {
3029         int i;
3030         skinframe_t *skinframe;
3031
3032         if (cls.state == ca_dedicated)
3033                 return NULL;
3034
3035         // if already loaded just return it, otherwise make a new skinframe
3036         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3037         if (skinframe && skinframe->base)
3038                 return skinframe;
3039
3040         skinframe->stain = NULL;
3041         skinframe->merged = NULL;
3042         skinframe->base = r_texture_notexture;
3043         skinframe->pants = NULL;
3044         skinframe->shirt = NULL;
3045         skinframe->nmap = r_texture_blanknormalmap;
3046         skinframe->gloss = NULL;
3047         skinframe->glow = NULL;
3048         skinframe->fog = NULL;
3049         skinframe->hasalpha = false;
3050
3051         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3052         if (!skindata)
3053                 return NULL;
3054
3055         if (developer_loading.integer)
3056                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3057
3058         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3059         if (textureflags & TEXF_ALPHA)
3060         {
3061                 for (i = 0;i < width * height;i++)
3062                 {
3063                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3064                         {
3065                                 skinframe->hasalpha = true;
3066                                 break;
3067                         }
3068                 }
3069                 if (r_loadfog && skinframe->hasalpha)
3070                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3071         }
3072
3073         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3074         //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]);
3075
3076         return skinframe;
3077 }
3078
3079 skinframe_t *R_SkinFrame_LoadMissing(void)
3080 {
3081         skinframe_t *skinframe;
3082
3083         if (cls.state == ca_dedicated)
3084                 return NULL;
3085
3086         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
3087         skinframe->stain = NULL;
3088         skinframe->merged = NULL;
3089         skinframe->base = r_texture_notexture;
3090         skinframe->pants = NULL;
3091         skinframe->shirt = NULL;
3092         skinframe->nmap = r_texture_blanknormalmap;
3093         skinframe->gloss = NULL;
3094         skinframe->glow = NULL;
3095         skinframe->fog = NULL;
3096         skinframe->hasalpha = false;
3097
3098         skinframe->avgcolor[0] = rand() / RAND_MAX;
3099         skinframe->avgcolor[1] = rand() / RAND_MAX;
3100         skinframe->avgcolor[2] = rand() / RAND_MAX;
3101         skinframe->avgcolor[3] = 1;
3102
3103         return skinframe;
3104 }
3105
3106 void R_Main_FreeViewCache(void)
3107 {
3108         if (r_refdef.viewcache.entityvisible)
3109                 Mem_Free(r_refdef.viewcache.entityvisible);
3110         if (r_refdef.viewcache.world_pvsbits)
3111                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3112         if (r_refdef.viewcache.world_leafvisible)
3113                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3114         if (r_refdef.viewcache.world_surfacevisible)
3115                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3116         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3117 }
3118
3119 void R_Main_ResizeViewCache(void)
3120 {
3121         int numentities = r_refdef.scene.numentities;
3122         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3123         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3124         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3125         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3126         if (r_refdef.viewcache.maxentities < numentities)
3127         {
3128                 r_refdef.viewcache.maxentities = numentities;
3129                 if (r_refdef.viewcache.entityvisible)
3130                         Mem_Free(r_refdef.viewcache.entityvisible);
3131                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3132         }
3133         if (r_refdef.viewcache.world_numclusters != numclusters)
3134         {
3135                 r_refdef.viewcache.world_numclusters = numclusters;
3136                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3137                 if (r_refdef.viewcache.world_pvsbits)
3138                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3139                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3140         }
3141         if (r_refdef.viewcache.world_numleafs != numleafs)
3142         {
3143                 r_refdef.viewcache.world_numleafs = numleafs;
3144                 if (r_refdef.viewcache.world_leafvisible)
3145                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3146                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3147         }
3148         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3149         {
3150                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3151                 if (r_refdef.viewcache.world_surfacevisible)
3152                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3153                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3154         }
3155 }
3156
3157 extern rtexture_t *loadingscreentexture;
3158 void gl_main_start(void)
3159 {
3160         loadingscreentexture = NULL;
3161         r_texture_blanknormalmap = NULL;
3162         r_texture_white = NULL;
3163         r_texture_grey128 = NULL;
3164         r_texture_black = NULL;
3165         r_texture_whitecube = NULL;
3166         r_texture_normalizationcube = NULL;
3167         r_texture_fogattenuation = NULL;
3168         r_texture_gammaramps = NULL;
3169
3170         switch(vid.renderpath)
3171         {
3172         case RENDERPATH_GL20:
3173                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3174                 Cvar_SetValueQuick(&gl_combine, 1);
3175                 Cvar_SetValueQuick(&r_glsl, 1);
3176                 r_loadnormalmap = true;
3177                 r_loadgloss = true;
3178                 r_loadfog = false;
3179                 break;
3180         case RENDERPATH_GL13:
3181                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3182                 Cvar_SetValueQuick(&gl_combine, 1);
3183                 Cvar_SetValueQuick(&r_glsl, 0);
3184                 r_loadnormalmap = false;
3185                 r_loadgloss = false;
3186                 r_loadfog = true;
3187                 break;
3188         case RENDERPATH_GL11:
3189                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3190                 Cvar_SetValueQuick(&gl_combine, 0);
3191                 Cvar_SetValueQuick(&r_glsl, 0);
3192                 r_loadnormalmap = false;
3193                 r_loadgloss = false;
3194                 r_loadfog = true;
3195                 break;
3196         }
3197
3198         R_AnimCache_Free();
3199         R_FrameData_Reset();
3200
3201         r_numqueries = 0;
3202         r_maxqueries = 0;
3203         memset(r_queries, 0, sizeof(r_queries));
3204
3205         r_qwskincache = NULL;
3206         r_qwskincache_size = 0;
3207
3208         // set up r_skinframe loading system for textures
3209         memset(&r_skinframe, 0, sizeof(r_skinframe));
3210         r_skinframe.loadsequence = 1;
3211         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3212
3213         r_main_texturepool = R_AllocTexturePool();
3214         R_BuildBlankTextures();
3215         R_BuildNoTexture();
3216         if (vid.support.arb_texture_cube_map)
3217         {
3218                 R_BuildWhiteCube();
3219                 R_BuildNormalizationCube();
3220         }
3221         r_texture_fogattenuation = NULL;
3222         r_texture_gammaramps = NULL;
3223         //r_texture_fogintensity = NULL;
3224         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3225         memset(&r_waterstate, 0, sizeof(r_waterstate));
3226         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3227         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3228         memset(&r_svbsp, 0, sizeof (r_svbsp));
3229
3230         r_refdef.fogmasktable_density = 0;
3231 }
3232
3233 void gl_main_shutdown(void)
3234 {
3235         R_AnimCache_Free();
3236         R_FrameData_Reset();
3237
3238         R_Main_FreeViewCache();
3239
3240         if (r_maxqueries)
3241                 qglDeleteQueriesARB(r_maxqueries, r_queries);
3242
3243         r_numqueries = 0;
3244         r_maxqueries = 0;
3245         memset(r_queries, 0, sizeof(r_queries));
3246
3247         r_qwskincache = NULL;
3248         r_qwskincache_size = 0;
3249
3250         // clear out the r_skinframe state
3251         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3252         memset(&r_skinframe, 0, sizeof(r_skinframe));
3253
3254         if (r_svbsp.nodes)
3255                 Mem_Free(r_svbsp.nodes);
3256         memset(&r_svbsp, 0, sizeof (r_svbsp));
3257         R_FreeTexturePool(&r_main_texturepool);
3258         loadingscreentexture = NULL;
3259         r_texture_blanknormalmap = NULL;
3260         r_texture_white = NULL;
3261         r_texture_grey128 = NULL;
3262         r_texture_black = NULL;
3263         r_texture_whitecube = NULL;
3264         r_texture_normalizationcube = NULL;
3265         r_texture_fogattenuation = NULL;
3266         r_texture_gammaramps = NULL;
3267         //r_texture_fogintensity = NULL;
3268         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3269         memset(&r_waterstate, 0, sizeof(r_waterstate));
3270         R_GLSL_Restart_f();
3271 }
3272
3273 extern void CL_ParseEntityLump(char *entitystring);
3274 void gl_main_newmap(void)
3275 {
3276         // FIXME: move this code to client
3277         int l;
3278         char *entities, entname[MAX_QPATH];
3279         if (r_qwskincache)
3280                 Mem_Free(r_qwskincache);
3281         r_qwskincache = NULL;
3282         r_qwskincache_size = 0;
3283         if (cl.worldmodel)
3284         {
3285                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
3286                 l = (int)strlen(entname) - 4;
3287                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
3288                 {
3289                         memcpy(entname + l, ".ent", 5);
3290                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3291                         {
3292                                 CL_ParseEntityLump(entities);
3293                                 Mem_Free(entities);
3294                                 return;
3295                         }
3296                 }
3297                 if (cl.worldmodel->brush.entities)
3298                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3299         }
3300         R_Main_FreeViewCache();
3301
3302         R_FrameData_Reset();
3303 }
3304
3305 void GL_Main_Init(void)
3306 {
3307         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3308
3309         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3310         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3311         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3312         if (gamemode == GAME_NEHAHRA)
3313         {
3314                 Cvar_RegisterVariable (&gl_fogenable);
3315                 Cvar_RegisterVariable (&gl_fogdensity);
3316                 Cvar_RegisterVariable (&gl_fogred);
3317                 Cvar_RegisterVariable (&gl_foggreen);
3318                 Cvar_RegisterVariable (&gl_fogblue);
3319                 Cvar_RegisterVariable (&gl_fogstart);
3320                 Cvar_RegisterVariable (&gl_fogend);
3321                 Cvar_RegisterVariable (&gl_skyclip);
3322         }
3323         Cvar_RegisterVariable(&r_motionblur);
3324         Cvar_RegisterVariable(&r_motionblur_maxblur);
3325         Cvar_RegisterVariable(&r_motionblur_bmin);
3326         Cvar_RegisterVariable(&r_motionblur_vmin);
3327         Cvar_RegisterVariable(&r_motionblur_vmax);
3328         Cvar_RegisterVariable(&r_motionblur_vcoeff);
3329         Cvar_RegisterVariable(&r_motionblur_randomize);
3330         Cvar_RegisterVariable(&r_damageblur);
3331         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3332         Cvar_RegisterVariable(&r_equalize_entities_minambient);
3333         Cvar_RegisterVariable(&r_equalize_entities_by);
3334         Cvar_RegisterVariable(&r_equalize_entities_to);
3335         Cvar_RegisterVariable(&r_depthfirst);
3336         Cvar_RegisterVariable(&r_useinfinitefarclip);
3337         Cvar_RegisterVariable(&r_farclip_base);
3338         Cvar_RegisterVariable(&r_farclip_world);
3339         Cvar_RegisterVariable(&r_nearclip);
3340         Cvar_RegisterVariable(&r_showbboxes);
3341         Cvar_RegisterVariable(&r_showsurfaces);
3342         Cvar_RegisterVariable(&r_showtris);
3343         Cvar_RegisterVariable(&r_shownormals);
3344         Cvar_RegisterVariable(&r_showlighting);
3345         Cvar_RegisterVariable(&r_showshadowvolumes);
3346         Cvar_RegisterVariable(&r_showcollisionbrushes);
3347         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3348         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3349         Cvar_RegisterVariable(&r_showdisabledepthtest);
3350         Cvar_RegisterVariable(&r_drawportals);
3351         Cvar_RegisterVariable(&r_drawentities);
3352         Cvar_RegisterVariable(&r_cullentities_trace);
3353         Cvar_RegisterVariable(&r_cullentities_trace_samples);
3354         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3355         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3356         Cvar_RegisterVariable(&r_cullentities_trace_delay);
3357         Cvar_RegisterVariable(&r_drawviewmodel);
3358         Cvar_RegisterVariable(&r_speeds);
3359         Cvar_RegisterVariable(&r_fullbrights);
3360         Cvar_RegisterVariable(&r_wateralpha);
3361         Cvar_RegisterVariable(&r_dynamic);
3362         Cvar_RegisterVariable(&r_fullbright);
3363         Cvar_RegisterVariable(&r_shadows);
3364         Cvar_RegisterVariable(&r_shadows_darken);
3365         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3366         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3367         Cvar_RegisterVariable(&r_shadows_throwdistance);
3368         Cvar_RegisterVariable(&r_shadows_throwdirection);
3369         Cvar_RegisterVariable(&r_q1bsp_skymasking);
3370         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3371         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3372         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3373         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3374         Cvar_RegisterVariable(&r_fog_exp2);
3375         Cvar_RegisterVariable(&r_drawfog);
3376         Cvar_RegisterVariable(&r_transparentdepthmasking);
3377         Cvar_RegisterVariable(&r_textureunits);
3378         Cvar_RegisterVariable(&gl_combine);
3379         Cvar_RegisterVariable(&r_glsl);
3380         Cvar_RegisterVariable(&r_glsl_deluxemapping);
3381         Cvar_RegisterVariable(&r_glsl_offsetmapping);
3382         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3383         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3384         Cvar_RegisterVariable(&r_glsl_postprocess);
3385         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3386         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3387         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3388         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3389         Cvar_RegisterVariable(&r_water);
3390         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3391         Cvar_RegisterVariable(&r_water_clippingplanebias);
3392         Cvar_RegisterVariable(&r_water_refractdistort);
3393         Cvar_RegisterVariable(&r_water_reflectdistort);
3394         Cvar_RegisterVariable(&r_lerpsprites);
3395         Cvar_RegisterVariable(&r_lerpmodels);
3396         Cvar_RegisterVariable(&r_lerplightstyles);
3397         Cvar_RegisterVariable(&r_waterscroll);
3398         Cvar_RegisterVariable(&r_bloom);
3399         Cvar_RegisterVariable(&r_bloom_colorscale);
3400         Cvar_RegisterVariable(&r_bloom_brighten);
3401         Cvar_RegisterVariable(&r_bloom_blur);
3402         Cvar_RegisterVariable(&r_bloom_resolution);
3403         Cvar_RegisterVariable(&r_bloom_colorexponent);
3404         Cvar_RegisterVariable(&r_bloom_colorsubtract);
3405         Cvar_RegisterVariable(&r_hdr);
3406         Cvar_RegisterVariable(&r_hdr_scenebrightness);
3407         Cvar_RegisterVariable(&r_hdr_glowintensity);
3408         Cvar_RegisterVariable(&r_hdr_range);
3409         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3410         Cvar_RegisterVariable(&developer_texturelogging);
3411         Cvar_RegisterVariable(&gl_lightmaps);
3412         Cvar_RegisterVariable(&r_test);
3413         Cvar_RegisterVariable(&r_batchmode);
3414         Cvar_RegisterVariable(&r_glsl_saturation);
3415         Cvar_RegisterVariable(&r_framedatasize);
3416         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3417                 Cvar_SetValue("r_fullbrights", 0);
3418         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3419
3420         Cvar_RegisterVariable(&r_track_sprites);
3421         Cvar_RegisterVariable(&r_track_sprites_flags);
3422         Cvar_RegisterVariable(&r_track_sprites_scalew);
3423         Cvar_RegisterVariable(&r_track_sprites_scaleh);
3424 }
3425
3426 extern void R_Textures_Init(void);
3427 extern void GL_Draw_Init(void);
3428 extern void GL_Main_Init(void);
3429 extern void R_Shadow_Init(void);
3430 extern void R_Sky_Init(void);
3431 extern void GL_Surf_Init(void);
3432 extern void R_Particles_Init(void);
3433 extern void R_Explosion_Init(void);
3434 extern void gl_backend_init(void);
3435 extern void Sbar_Init(void);
3436 extern void R_LightningBeams_Init(void);
3437 extern void Mod_RenderInit(void);
3438
3439 void Render_Init(void)
3440 {
3441         gl_backend_init();
3442         R_Textures_Init();
3443         GL_Main_Init();
3444         GL_Draw_Init();
3445         R_Shadow_Init();
3446         R_Sky_Init();
3447         GL_Surf_Init();
3448         Sbar_Init();
3449         R_Particles_Init();
3450         R_Explosion_Init();
3451         R_LightningBeams_Init();
3452         Mod_RenderInit();
3453 }
3454
3455 /*
3456 ===============
3457 GL_Init
3458 ===============
3459 */
3460 extern char *ENGINE_EXTENSIONS;
3461 void GL_Init (void)
3462 {
3463         gl_renderer = (const char *)qglGetString(GL_RENDERER);
3464         gl_vendor = (const char *)qglGetString(GL_VENDOR);
3465         gl_version = (const char *)qglGetString(GL_VERSION);
3466         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3467
3468         if (!gl_extensions)
3469                 gl_extensions = "";
3470         if (!gl_platformextensions)
3471                 gl_platformextensions = "";
3472
3473         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3474         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3475         Con_Printf("GL_VERSION: %s\n", gl_version);
3476         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3477         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3478
3479         VID_CheckExtensions();
3480
3481         // LordHavoc: report supported extensions
3482         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3483
3484         // clear to black (loading plaque will be seen over this)
3485         CHECKGLERROR
3486         qglClearColor(0,0,0,1);CHECKGLERROR
3487         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3488 }
3489
3490 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3491 {
3492         int i;
3493         mplane_t *p;
3494         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3495         {
3496                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3497                 if (i == 4)
3498                         continue;
3499                 p = r_refdef.view.frustum + i;
3500                 switch(p->signbits)
3501                 {
3502                 default:
3503                 case 0:
3504                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3505                                 return true;
3506                         break;
3507                 case 1:
3508                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3509                                 return true;
3510                         break;
3511                 case 2:
3512                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3513                                 return true;
3514                         break;
3515                 case 3:
3516                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3517                                 return true;
3518                         break;
3519                 case 4:
3520                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3521                                 return true;
3522                         break;
3523                 case 5:
3524                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3525                                 return true;
3526                         break;
3527                 case 6:
3528                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3529                                 return true;
3530                         break;
3531                 case 7:
3532                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3533                                 return true;
3534                         break;
3535                 }
3536         }
3537         return false;
3538 }
3539
3540 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3541 {
3542         int i;
3543         const mplane_t *p;
3544         for (i = 0;i < numplanes;i++)
3545         {
3546                 p = planes + i;
3547                 switch(p->signbits)
3548                 {
3549                 default:
3550                 case 0:
3551                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3552                                 return true;
3553                         break;
3554                 case 1:
3555                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3556                                 return true;
3557                         break;
3558                 case 2:
3559                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3560                                 return true;
3561                         break;
3562                 case 3:
3563                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3564                                 return true;
3565                         break;
3566                 case 4:
3567                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3568                                 return true;
3569                         break;
3570                 case 5:
3571                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3572                                 return true;
3573                         break;
3574                 case 6:
3575                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3576                                 return true;
3577                         break;
3578                 case 7:
3579                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3580                                 return true;
3581                         break;
3582                 }
3583         }
3584         return false;
3585 }
3586
3587 //==================================================================================
3588
3589 // LordHavoc: this stores temporary data used within the same frame
3590
3591 qboolean r_framedata_failed;
3592 static size_t r_framedata_size;
3593 static size_t r_framedata_current;
3594 static void *r_framedata_base;
3595
3596 void R_FrameData_Reset(void)
3597 {
3598         if (r_framedata_base);
3599                 Mem_Free(r_framedata_base);
3600         r_framedata_base = NULL;
3601         r_framedata_size = 0;
3602         r_framedata_current = 0;
3603         r_framedata_failed = false;
3604 }
3605
3606 void R_FrameData_NewFrame(void)
3607 {
3608         size_t wantedsize;
3609         if (r_framedata_failed)
3610                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
3611         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
3612         wantedsize = bound(65536, wantedsize, 128*1024*1024);
3613         if (r_framedata_size != wantedsize)
3614         {
3615                 r_framedata_size = wantedsize;
3616                 if (r_framedata_base);
3617                         Mem_Free(r_framedata_base);
3618                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
3619         }
3620         r_framedata_current = 0;
3621         r_framedata_failed = false;
3622 }
3623
3624 void *R_FrameData_Alloc(size_t size)
3625 {
3626         void *data;
3627
3628         // align to 16 byte boundary
3629         size = (size + 15) & ~15;
3630         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
3631         r_framedata_current += size;
3632
3633         // check overflow
3634         if (r_framedata_current > r_framedata_size)
3635                 r_framedata_failed = true;
3636
3637         // return NULL on everything after a failure
3638         if (r_framedata_failed)
3639                 return NULL;
3640
3641         return data;
3642 }
3643
3644 void *R_FrameData_Store(size_t size, void *data)
3645 {
3646         void *d = R_FrameData_Alloc(size);
3647         if (d)
3648                 memcpy(d, data, size);
3649         return d;
3650 }
3651
3652 //==================================================================================
3653
3654 // LordHavoc: animcache originally written by Echon, rewritten since then
3655
3656 /**
3657  * Animation cache prevents re-generating mesh data for an animated model
3658  * multiple times in one frame for lighting, shadowing, reflections, etc.
3659  */
3660
3661 void R_AnimCache_Free(void)
3662 {
3663 }
3664
3665 void R_AnimCache_ClearCache(void)
3666 {
3667         int i;
3668         entity_render_t *ent;
3669
3670         for (i = 0;i < r_refdef.scene.numentities;i++)
3671         {
3672                 ent = r_refdef.scene.entities[i];
3673                 ent->animcache_vertex3f = NULL;
3674                 ent->animcache_normal3f = NULL;
3675                 ent->animcache_svector3f = NULL;
3676                 ent->animcache_tvector3f = NULL;
3677         }
3678 }
3679
3680 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3681 {
3682         dp_model_t *model = ent->model;
3683         int numvertices;
3684         // see if it's already cached this frame
3685         if (ent->animcache_vertex3f)
3686         {
3687                 // add normals/tangents if needed
3688                 if (wantnormals || wanttangents)
3689                 {
3690                         if (ent->animcache_normal3f)
3691                                 wantnormals = false;
3692                         if (ent->animcache_svector3f)
3693                                 wanttangents = false;
3694                         if (wantnormals || wanttangents)
3695                         {
3696                                 numvertices = model->surfmesh.num_vertices;
3697                                 if (wantnormals)
3698                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3699                                 if (wanttangents)
3700                                 {
3701                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3702                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3703                                 }
3704                                 if (!r_framedata_failed)
3705                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
3706                         }
3707                 }
3708         }
3709         else
3710         {
3711                 // see if this ent is worth caching
3712                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
3713                         return false;
3714                 // get some memory for this entity and generate mesh data
3715                 numvertices = model->surfmesh.num_vertices;
3716                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3717                 if (wantnormals)
3718                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3719                 if (wanttangents)
3720                 {
3721                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3722                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3723                 }
3724                 if (!r_framedata_failed)
3725                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
3726         }
3727         return !r_framedata_failed;
3728 }
3729
3730 void R_AnimCache_CacheVisibleEntities(void)
3731 {
3732         int i;
3733         qboolean wantnormals = !r_showsurfaces.integer;
3734         qboolean wanttangents = !r_showsurfaces.integer;
3735
3736         switch(vid.renderpath)
3737         {
3738         case RENDERPATH_GL20:
3739                 break;
3740         case RENDERPATH_GL13:
3741         case RENDERPATH_GL11:
3742                 wanttangents = false;
3743                 break;
3744         }
3745
3746         // TODO: thread this
3747         // NOTE: R_PrepareRTLights() also caches entities
3748
3749         for (i = 0;i < r_refdef.scene.numentities;i++)
3750                 if (r_refdef.viewcache.entityvisible[i])
3751                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3752
3753         if (r_shadows.integer)
3754                 for (i = 0;i < r_refdef.scene.numentities;i++)
3755                         if (!r_refdef.viewcache.entityvisible[i])
3756                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
3757 }
3758
3759 //==================================================================================
3760
3761 static void R_View_UpdateEntityLighting (void)
3762 {
3763         int i;
3764         entity_render_t *ent;
3765         vec3_t tempdiffusenormal, avg;
3766         vec_t f, fa, fd, fdd;
3767
3768         for (i = 0;i < r_refdef.scene.numentities;i++)
3769         {
3770                 ent = r_refdef.scene.entities[i];
3771
3772                 // skip unseen models
3773                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3774                         continue;
3775
3776                 // skip bsp models
3777                 if (ent->model && ent->model->brush.num_leafs)
3778                 {
3779                         // TODO: use modellight for r_ambient settings on world?
3780                         VectorSet(ent->modellight_ambient, 0, 0, 0);
3781                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
3782                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
3783                         continue;
3784                 }
3785
3786                 // fetch the lighting from the worldmodel data
3787                 VectorClear(ent->modellight_ambient);
3788                 VectorClear(ent->modellight_diffuse);
3789                 VectorClear(tempdiffusenormal);
3790                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3791                 {
3792                         vec3_t org;
3793                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3794                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3795                         if(ent->flags & RENDER_EQUALIZE)
3796                         {
3797                                 // first fix up ambient lighting...
3798                                 if(r_equalize_entities_minambient.value > 0)
3799                                 {
3800                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3801                                         if(fd > 0)
3802                                         {
3803                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3804                                                 if(fa < r_equalize_entities_minambient.value * fd)
3805                                                 {
3806                                                         // solve:
3807                                                         //   fa'/fd' = minambient
3808                                                         //   fa'+0.25*fd' = fa+0.25*fd
3809                                                         //   ...
3810                                                         //   fa' = fd' * minambient
3811                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
3812                                                         //   ...
3813                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3814                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3815                                                         //   ...
3816                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3817                                                         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
3818                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3819                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3820                                                 }
3821                                         }
3822                                 }
3823
3824                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3825                                 {
3826                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3827                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3828                                         if(f > 0)
3829                                         {
3830                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3831                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3832                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3833                                         }
3834                                 }
3835                         }
3836                 }
3837                 else // highly rare
3838                         VectorSet(ent->modellight_ambient, 1, 1, 1);
3839
3840                 // move the light direction into modelspace coordinates for lighting code
3841                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3842                 if(VectorLength2(ent->modellight_lightdir) == 0)
3843                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3844                 VectorNormalize(ent->modellight_lightdir);
3845         }
3846 }
3847
3848 #define MAX_LINEOFSIGHTTRACES 64
3849
3850 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3851 {
3852         int i;
3853         vec3_t boxmins, boxmaxs;
3854         vec3_t start;
3855         vec3_t end;
3856         dp_model_t *model = r_refdef.scene.worldmodel;
3857
3858         if (!model || !model->brush.TraceLineOfSight)
3859                 return true;
3860
3861         // expand the box a little
3862         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3863         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3864         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3865         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3866         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3867         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3868
3869         // try center
3870         VectorCopy(eye, start);
3871         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3872         if (model->brush.TraceLineOfSight(model, start, end))
3873                 return true;
3874
3875         // try various random positions
3876         for (i = 0;i < numsamples;i++)
3877         {
3878                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3879                 if (model->brush.TraceLineOfSight(model, start, end))
3880                         return true;
3881         }
3882
3883         return false;
3884 }
3885
3886
3887 static void R_View_UpdateEntityVisible (void)
3888 {
3889         int i;
3890         int renderimask;
3891         int samples;
3892         entity_render_t *ent;
3893
3894         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3895         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3896         {
3897                 // worldmodel can check visibility
3898                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3899                 for (i = 0;i < r_refdef.scene.numentities;i++)
3900                 {
3901                         ent = r_refdef.scene.entities[i];
3902                         if (!(ent->flags & renderimask))
3903                         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)))
3904                         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))
3905                                 r_refdef.viewcache.entityvisible[i] = true;
3906                 }
3907                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3908                 {
3909                         for (i = 0;i < r_refdef.scene.numentities;i++)
3910                         {
3911                                 ent = r_refdef.scene.entities[i];
3912                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3913                                 {
3914                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3915                                         if (samples < 0)
3916                                                 continue; // temp entities do pvs only
3917                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3918                                                 ent->last_trace_visibility = realtime;
3919                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3920                                                 r_refdef.viewcache.entityvisible[i] = 0;
3921                                 }
3922                         }
3923                 }
3924         }
3925         else
3926         {
3927                 // no worldmodel or it can't check visibility
3928                 for (i = 0;i < r_refdef.scene.numentities;i++)
3929                 {
3930                         ent = r_refdef.scene.entities[i];
3931                         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));
3932                 }
3933         }
3934 }
3935
3936 /// only used if skyrendermasked, and normally returns false
3937 int R_DrawBrushModelsSky (void)
3938 {
3939         int i, sky;
3940         entity_render_t *ent;
3941
3942         sky = false;
3943         for (i = 0;i < r_refdef.scene.numentities;i++)
3944         {
3945                 if (!r_refdef.viewcache.entityvisible[i])
3946                         continue;
3947                 ent = r_refdef.scene.entities[i];
3948                 if (!ent->model || !ent->model->DrawSky)
3949                         continue;
3950                 ent->model->DrawSky(ent);
3951                 sky = true;
3952         }
3953         return sky;
3954 }
3955
3956 static void R_DrawNoModel(entity_render_t *ent);
3957 static void R_DrawModels(void)
3958 {
3959         int i;
3960         entity_render_t *ent;
3961
3962         for (i = 0;i < r_refdef.scene.numentities;i++)
3963         {
3964                 if (!r_refdef.viewcache.entityvisible[i])
3965                         continue;
3966                 ent = r_refdef.scene.entities[i];
3967                 r_refdef.stats.entities++;
3968                 if (ent->model && ent->model->Draw != NULL)
3969                         ent->model->Draw(ent);
3970                 else
3971                         R_DrawNoModel(ent);
3972         }
3973 }
3974
3975 static void R_DrawModelsDepth(void)
3976 {
3977         int i;
3978         entity_render_t *ent;
3979
3980         for (i = 0;i < r_refdef.scene.numentities;i++)
3981         {
3982                 if (!r_refdef.viewcache.entityvisible[i])
3983                         continue;
3984                 ent = r_refdef.scene.entities[i];
3985                 if (ent->model && ent->model->DrawDepth != NULL)
3986                         ent->model->DrawDepth(ent);
3987         }
3988 }
3989
3990 static void R_DrawModelsDebug(void)
3991 {
3992         int i;
3993         entity_render_t *ent;
3994
3995         for (i = 0;i < r_refdef.scene.numentities;i++)
3996         {
3997                 if (!r_refdef.viewcache.entityvisible[i])
3998                         continue;
3999                 ent = r_refdef.scene.entities[i];
4000                 if (ent->model && ent->model->DrawDebug != NULL)
4001                         ent->model->DrawDebug(ent);
4002         }
4003 }
4004
4005 static void R_DrawModelsAddWaterPlanes(void)
4006 {
4007         int i;
4008         entity_render_t *ent;
4009
4010         for (i = 0;i < r_refdef.scene.numentities;i++)
4011         {
4012                 if (!r_refdef.viewcache.entityvisible[i])
4013                         continue;
4014                 ent = r_refdef.scene.entities[i];
4015                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4016                         ent->model->DrawAddWaterPlanes(ent);
4017         }
4018 }
4019
4020 static void R_View_SetFrustum(void)
4021 {
4022         int i;
4023         double slopex, slopey;
4024         vec3_t forward, left, up, origin;
4025
4026         // we can't trust r_refdef.view.forward and friends in reflected scenes
4027         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4028
4029 #if 0
4030         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4031         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4032         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4033         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4034         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4035         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4036         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4037         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4038         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4039         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4040         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4041         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4042 #endif
4043
4044 #if 0
4045         zNear = r_refdef.nearclip;
4046         nudge = 1.0 - 1.0 / (1<<23);
4047         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4048         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4049         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4050         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4051         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4052         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4053         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4054         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4055 #endif
4056
4057
4058
4059 #if 0
4060         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4061         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4062         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4063         r_refdef.view.frustum[0].dist = m[15] - m[12];
4064
4065         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4066         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4067         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4068         r_refdef.view.frustum[1].dist = m[15] + m[12];
4069
4070         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4071         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4072         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4073         r_refdef.view.frustum[2].dist = m[15] - m[13];
4074
4075         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4076         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4077         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4078         r_refdef.view.frustum[3].dist = m[15] + m[13];
4079
4080         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4081         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4082         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4083         r_refdef.view.frustum[4].dist = m[15] - m[14];
4084
4085         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4086         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4087         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4088         r_refdef.view.frustum[5].dist = m[15] + m[14];
4089 #endif
4090
4091         if (r_refdef.view.useperspective)
4092         {
4093                 slopex = 1.0 / r_refdef.view.frustum_x;
4094                 slopey = 1.0 / r_refdef.view.frustum_y;
4095                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4096                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
4097                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
4098                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
4099                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4100
4101                 // Leaving those out was a mistake, those were in the old code, and they
4102                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4103                 // I couldn't reproduce it after adding those normalizations. --blub
4104                 VectorNormalize(r_refdef.view.frustum[0].normal);
4105                 VectorNormalize(r_refdef.view.frustum[1].normal);
4106                 VectorNormalize(r_refdef.view.frustum[2].normal);
4107                 VectorNormalize(r_refdef.view.frustum[3].normal);
4108
4109                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4110                 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]);
4111                 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]);
4112                 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]);
4113                 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]);
4114
4115                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4116                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4117                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4118                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4119                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4120         }
4121         else
4122         {
4123                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4124                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4125                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4126                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4127                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4128                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4129                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4130                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4131                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4132                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4133         }
4134         r_refdef.view.numfrustumplanes = 5;
4135
4136         if (r_refdef.view.useclipplane)
4137         {
4138                 r_refdef.view.numfrustumplanes = 6;
4139                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4140         }
4141
4142         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4143                 PlaneClassify(r_refdef.view.frustum + i);
4144
4145         // LordHavoc: note to all quake engine coders, Quake had a special case
4146         // for 90 degrees which assumed a square view (wrong), so I removed it,
4147         // Quake2 has it disabled as well.
4148
4149         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4150         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4151         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4152         //PlaneClassify(&frustum[0]);
4153
4154         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4155         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4156         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4157         //PlaneClassify(&frustum[1]);
4158
4159         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4160         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4161         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4162         //PlaneClassify(&frustum[2]);
4163
4164         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4165         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4166         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4167         //PlaneClassify(&frustum[3]);
4168
4169         // nearclip plane
4170         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4171         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4172         //PlaneClassify(&frustum[4]);
4173 }
4174
4175 void R_View_Update(void)
4176 {
4177         R_Main_ResizeViewCache();
4178         R_View_SetFrustum();
4179         R_View_WorldVisibility(r_refdef.view.useclipplane);
4180         R_View_UpdateEntityVisible();
4181         R_View_UpdateEntityLighting();
4182 }
4183
4184 void R_SetupView(qboolean allowwaterclippingplane)
4185 {
4186         const double *customclipplane = NULL;
4187         double plane[4];
4188         if (r_refdef.view.useclipplane && allowwaterclippingplane)
4189         {
4190                 // LordHavoc: couldn't figure out how to make this approach the
4191                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4192                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4193                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4194                         dist = r_refdef.view.clipplane.dist;
4195                 plane[0] = r_refdef.view.clipplane.normal[0];
4196                 plane[1] = r_refdef.view.clipplane.normal[1];
4197                 plane[2] = r_refdef.view.clipplane.normal[2];
4198                 plane[3] = dist;
4199                 customclipplane = plane;
4200         }
4201
4202         if (!r_refdef.view.useperspective)
4203                 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);
4204         else if (vid.stencil && r_useinfinitefarclip.integer)
4205                 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);
4206         else
4207                 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);
4208         R_SetViewport(&r_refdef.view.viewport);
4209 }
4210
4211 void R_ResetViewRendering2D(void)
4212 {
4213         r_viewport_t viewport;
4214         DrawQ_Finish();
4215
4216         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4217         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);
4218         R_SetViewport(&viewport);
4219         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
4220         GL_Color(1, 1, 1, 1);
4221         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4222         GL_BlendFunc(GL_ONE, GL_ZERO);
4223         GL_AlphaTest(false);
4224         GL_ScissorTest(false);
4225         GL_DepthMask(false);
4226         GL_DepthRange(0, 1);
4227         GL_DepthTest(false);
4228         R_Mesh_Matrix(&identitymatrix);
4229         R_Mesh_ResetTextureState();
4230         GL_PolygonOffset(0, 0);
4231         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4232         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4233         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4234         qglStencilMask(~0);CHECKGLERROR
4235         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4236         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4237         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
4238         R_SetupGenericShader(true);
4239 }
4240
4241 void R_ResetViewRendering3D(void)
4242 {
4243         DrawQ_Finish();
4244
4245         R_SetupView(true);
4246         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4247         GL_Color(1, 1, 1, 1);
4248         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4249         GL_BlendFunc(GL_ONE, GL_ZERO);
4250         GL_AlphaTest(false);
4251         GL_ScissorTest(true);
4252         GL_DepthMask(true);
4253         GL_DepthRange(0, 1);
4254         GL_DepthTest(true);
4255         R_Mesh_Matrix(&identitymatrix);
4256         R_Mesh_ResetTextureState();
4257         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4258         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4259         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4260         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4261         qglStencilMask(~0);CHECKGLERROR
4262         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4263         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4264         GL_CullFace(r_refdef.view.cullface_back);
4265         R_SetupGenericShader(true);
4266 }
4267
4268 void R_RenderScene(void);
4269 void R_RenderWaterPlanes(void);
4270
4271 static void R_Water_StartFrame(void)
4272 {
4273         int i;
4274         int waterwidth, waterheight, texturewidth, textureheight;
4275         r_waterstate_waterplane_t *p;
4276
4277         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
4278                 return;
4279
4280         switch(vid.renderpath)
4281         {
4282         case RENDERPATH_GL20:
4283                 break;
4284         case RENDERPATH_GL13:
4285         case RENDERPATH_GL11:
4286                 return;
4287         }
4288
4289         // set waterwidth and waterheight to the water resolution that will be
4290         // used (often less than the screen resolution for faster rendering)
4291         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4292         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4293
4294         // calculate desired texture sizes
4295         // can't use water if the card does not support the texture size
4296         if (!r_water.integer || r_showsurfaces.integer)
4297                 texturewidth = textureheight = waterwidth = waterheight = 0;
4298         else if (vid.support.arb_texture_non_power_of_two)
4299         {
4300                 texturewidth = waterwidth;
4301                 textureheight = waterheight;
4302         }
4303         else
4304         {
4305                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
4306                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
4307         }
4308
4309         // allocate textures as needed
4310         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4311         {
4312                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4313                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4314                 {
4315                         if (p->texture_refraction)
4316                                 R_FreeTexture(p->texture_refraction);
4317                         p->texture_refraction = NULL;
4318                         if (p->texture_reflection)
4319                                 R_FreeTexture(p->texture_reflection);
4320                         p->texture_reflection = NULL;
4321                 }
4322                 memset(&r_waterstate, 0, sizeof(r_waterstate));
4323                 r_waterstate.texturewidth = texturewidth;
4324                 r_waterstate.textureheight = textureheight;
4325         }
4326
4327         if (r_waterstate.texturewidth)
4328         {
4329                 r_waterstate.enabled = true;
4330
4331                 // when doing a reduced render (HDR) we want to use a smaller area
4332                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4333                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4334
4335                 // set up variables that will be used in shader setup
4336                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4337                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4338                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4339                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4340         }
4341
4342         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4343         r_waterstate.numwaterplanes = 0;
4344 }
4345
4346 void R_Water_AddWaterPlane(msurface_t *surface)
4347 {
4348         int triangleindex, planeindex;
4349         const int *e;
4350         vec3_t vert[3];
4351         vec3_t normal;
4352         vec3_t center;
4353         mplane_t plane;
4354         r_waterstate_waterplane_t *p;
4355         texture_t *t = R_GetCurrentTexture(surface->texture);
4356         // just use the first triangle with a valid normal for any decisions
4357         VectorClear(normal);
4358         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4359         {
4360                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4361                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4362                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4363                 TriangleNormal(vert[0], vert[1], vert[2], normal);
4364                 if (VectorLength2(normal) >= 0.001)
4365                         break;
4366         }
4367
4368         VectorCopy(normal, plane.normal);
4369         VectorNormalize(plane.normal);
4370         plane.dist = DotProduct(vert[0], plane.normal);
4371         PlaneClassify(&plane);
4372         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4373         {
4374                 // skip backfaces (except if nocullface is set)
4375                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4376                         return;
4377                 VectorNegate(plane.normal, plane.normal);
4378                 plane.dist *= -1;
4379                 PlaneClassify(&plane);
4380         }
4381
4382
4383         // find a matching plane if there is one
4384         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4385                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4386                         break;
4387         if (planeindex >= r_waterstate.maxwaterplanes)
4388                 return; // nothing we can do, out of planes
4389
4390         // if this triangle does not fit any known plane rendered this frame, add one
4391         if (planeindex >= r_waterstate.numwaterplanes)
4392         {
4393                 // store the new plane
4394                 r_waterstate.numwaterplanes++;
4395                 p->plane = plane;
4396                 // clear materialflags and pvs
4397                 p->materialflags = 0;
4398                 p->pvsvalid = false;
4399         }
4400         // merge this surface's materialflags into the waterplane
4401         p->materialflags |= t->currentmaterialflags;
4402         // merge this surface's PVS into the waterplane
4403         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4404         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4405          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4406         {
4407                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4408                 p->pvsvalid = true;
4409         }
4410 }
4411
4412 static void R_Water_ProcessPlanes(void)
4413 {
4414         r_refdef_view_t originalview;
4415         r_refdef_view_t myview;
4416         int planeindex;
4417         r_waterstate_waterplane_t *p;
4418
4419         originalview = r_refdef.view;
4420
4421         // make sure enough textures are allocated
4422         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4423         {
4424                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4425                 {
4426                         if (!p->texture_refraction)
4427                                 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 | TEXF_ALWAYSPRECACHE, NULL);
4428                         if (!p->texture_refraction)
4429                                 goto error;
4430                 }
4431
4432                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4433                 {
4434                         if (!p->texture_reflection)
4435                                 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 | TEXF_ALWAYSPRECACHE, NULL);
4436                         if (!p->texture_reflection)
4437                                 goto error;
4438                 }
4439         }
4440
4441         // render views
4442         r_refdef.view = originalview;
4443         r_refdef.view.showdebug = false;
4444         r_refdef.view.width = r_waterstate.waterwidth;
4445         r_refdef.view.height = r_waterstate.waterheight;
4446         r_refdef.view.useclipplane = true;
4447         myview = r_refdef.view;
4448         r_waterstate.renderingscene = true;
4449         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4450         {
4451                 // render the normal view scene and copy into texture
4452                 // (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)
4453                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4454                 {
4455                         r_refdef.view = myview;
4456                         r_refdef.view.clipplane = p->plane;
4457                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4458                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4459                         PlaneClassify(&r_refdef.view.clipplane);
4460
4461                         R_ResetViewRendering3D();
4462                         R_ClearScreen(r_refdef.fogenabled);
4463                         R_View_Update();
4464                         R_RenderScene();
4465
4466                         // copy view into the screen texture
4467                         R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4468                         GL_ActiveTexture(0);
4469                         CHECKGLERROR
4470                         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4471                 }
4472
4473                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4474                 {
4475                         r_refdef.view = myview;
4476                         // render reflected scene and copy into texture
4477                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4478                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4479                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4480                         r_refdef.view.clipplane = p->plane;
4481                         // reverse the cullface settings for this render
4482                         r_refdef.view.cullface_front = GL_FRONT;
4483                         r_refdef.view.cullface_back = GL_BACK;
4484                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4485                         {
4486                                 r_refdef.view.usecustompvs = true;
4487                                 if (p->pvsvalid)
4488                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4489                                 else
4490                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4491                         }
4492
4493                         R_ResetViewRendering3D();
4494                         R_ClearScreen(r_refdef.fogenabled);
4495                         R_View_Update();
4496                         R_RenderScene();
4497
4498                         R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4499                         GL_ActiveTexture(0);
4500                         CHECKGLERROR
4501                         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4502                 }
4503         }
4504         r_waterstate.renderingscene = false;
4505         r_refdef.view = originalview;
4506         R_ResetViewRendering3D();
4507         R_ClearScreen(r_refdef.fogenabled);
4508         R_View_Update();
4509         return;
4510 error:
4511         r_refdef.view = originalview;
4512         r_waterstate.renderingscene = false;
4513         Cvar_SetValueQuick(&r_water, 0);
4514         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
4515         return;
4516 }
4517
4518 void R_Bloom_StartFrame(void)
4519 {
4520         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4521
4522         switch(vid.renderpath)
4523         {
4524         case RENDERPATH_GL20:
4525                 break;
4526         case RENDERPATH_GL13:
4527         case RENDERPATH_GL11:
4528                 return;
4529         }
4530
4531         // set bloomwidth and bloomheight to the bloom resolution that will be
4532         // used (often less than the screen resolution for faster rendering)
4533         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4534         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4535         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4536         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
4537         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
4538
4539         // calculate desired texture sizes
4540         if (vid.support.arb_texture_non_power_of_two)
4541         {
4542                 screentexturewidth = r_refdef.view.width;
4543                 screentextureheight = r_refdef.view.height;
4544                 bloomtexturewidth = r_bloomstate.bloomwidth;
4545                 bloomtextureheight = r_bloomstate.bloomheight;
4546         }
4547         else
4548         {
4549                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
4550                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
4551                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
4552                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
4553         }
4554
4555         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))
4556         {
4557                 Cvar_SetValueQuick(&r_hdr, 0);
4558                 Cvar_SetValueQuick(&r_bloom, 0);
4559                 Cvar_SetValueQuick(&r_motionblur, 0);
4560                 Cvar_SetValueQuick(&r_damageblur, 0);
4561         }
4562
4563         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)))
4564                 screentexturewidth = screentextureheight = 0;
4565         if (!r_hdr.integer && !r_bloom.integer)
4566                 bloomtexturewidth = bloomtextureheight = 0;
4567
4568         // allocate textures as needed
4569         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4570         {
4571                 if (r_bloomstate.texture_screen)
4572                         R_FreeTexture(r_bloomstate.texture_screen);
4573                 r_bloomstate.texture_screen = NULL;
4574                 r_bloomstate.screentexturewidth = screentexturewidth;
4575                 r_bloomstate.screentextureheight = screentextureheight;
4576                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4577                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
4578         }
4579         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4580         {
4581                 if (r_bloomstate.texture_bloom)
4582                         R_FreeTexture(r_bloomstate.texture_bloom);
4583                 r_bloomstate.texture_bloom = NULL;
4584                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4585                 r_bloomstate.bloomtextureheight = bloomtextureheight;
4586                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4587                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
4588         }
4589
4590         // when doing a reduced render (HDR) we want to use a smaller area
4591         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4592         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4593         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4594         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4595         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4596
4597         // set up a texcoord array for the full resolution screen image
4598         // (we have to keep this around to copy back during final render)
4599         r_bloomstate.screentexcoord2f[0] = 0;
4600         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
4601         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
4602         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
4603         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
4604         r_bloomstate.screentexcoord2f[5] = 0;
4605         r_bloomstate.screentexcoord2f[6] = 0;
4606         r_bloomstate.screentexcoord2f[7] = 0;
4607
4608         // set up a texcoord array for the reduced resolution bloom image
4609         // (which will be additive blended over the screen image)
4610         r_bloomstate.bloomtexcoord2f[0] = 0;
4611         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4612         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
4613         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4614         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
4615         r_bloomstate.bloomtexcoord2f[5] = 0;
4616         r_bloomstate.bloomtexcoord2f[6] = 0;
4617         r_bloomstate.bloomtexcoord2f[7] = 0;
4618
4619         if (r_hdr.integer || r_bloom.integer)
4620         {
4621                 r_bloomstate.enabled = true;
4622                 r_bloomstate.hdr = r_hdr.integer != 0;
4623         }
4624
4625         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);
4626 }
4627
4628 void R_Bloom_CopyBloomTexture(float colorscale)
4629 {
4630         r_refdef.stats.bloom++;
4631
4632         // scale down screen texture to the bloom texture size
4633         CHECKGLERROR
4634         R_SetViewport(&r_bloomstate.viewport);
4635         GL_BlendFunc(GL_ONE, GL_ZERO);
4636         GL_Color(colorscale, colorscale, colorscale, 1);
4637         // TODO: optimize with multitexture or GLSL
4638         R_SetupGenericShader(true);
4639         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4640         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4641         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4642         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4643
4644         // we now have a bloom image in the framebuffer
4645         // copy it into the bloom image texture for later processing
4646         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4647         GL_ActiveTexture(0);
4648         CHECKGLERROR
4649         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4650         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4651 }
4652
4653 void R_Bloom_CopyHDRTexture(void)
4654 {
4655         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4656         GL_ActiveTexture(0);
4657         CHECKGLERROR
4658         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4659         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4660 }
4661
4662 void R_Bloom_MakeTexture(void)
4663 {
4664         int x, range, dir;
4665         float xoffset, yoffset, r, brighten;
4666
4667         r_refdef.stats.bloom++;
4668
4669         R_ResetViewRendering2D();
4670         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4671         R_Mesh_ColorPointer(NULL, 0, 0);
4672         R_SetupGenericShader(true);
4673
4674         // we have a bloom image in the framebuffer
4675         CHECKGLERROR
4676         R_SetViewport(&r_bloomstate.viewport);
4677
4678         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4679         {
4680                 x *= 2;
4681                 r = bound(0, r_bloom_colorexponent.value / x, 1);
4682                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4683                 GL_Color(r, r, r, 1);
4684                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4685                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4686                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4687                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4688
4689                 // copy the vertically blurred bloom view to a texture
4690                 GL_ActiveTexture(0);
4691                 CHECKGLERROR
4692                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4693                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4694         }
4695
4696         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4697         brighten = r_bloom_brighten.value;
4698         if (r_hdr.integer)
4699                 brighten *= r_hdr_range.value;
4700         brighten = sqrt(brighten);
4701         if(range >= 1)
4702                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4703         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4704         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4705
4706         for (dir = 0;dir < 2;dir++)
4707         {
4708                 // blend on at multiple vertical offsets to achieve a vertical blur
4709                 // TODO: do offset blends using GLSL
4710                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4711                 GL_BlendFunc(GL_ONE, GL_ZERO);
4712                 for (x = -range;x <= range;x++)
4713                 {
4714                         if (!dir){xoffset = 0;yoffset = x;}
4715                         else {xoffset = x;yoffset = 0;}
4716                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
4717                         yoffset /= (float)r_bloomstate.bloomtextureheight;
4718                         // compute a texcoord array with the specified x and y offset
4719                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4720                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4721                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4722                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4723                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4724                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4725                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4726                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4727                         // this r value looks like a 'dot' particle, fading sharply to
4728                         // black at the edges
4729                         // (probably not realistic but looks good enough)
4730                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4731                         //r = brighten/(range*2+1);
4732                         r = brighten / (range * 2 + 1);
4733                         if(range >= 1)
4734                                 r *= (1 - x*x/(float)(range*range));
4735                         GL_Color(r, r, r, 1);
4736                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4737                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4738                         GL_BlendFunc(GL_ONE, GL_ONE);
4739                 }
4740
4741                 // copy the vertically blurred bloom view to a texture
4742                 GL_ActiveTexture(0);
4743                 CHECKGLERROR
4744                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4745                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4746         }
4747
4748         // apply subtract last
4749         // (just like it would be in a GLSL shader)
4750         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
4751         {
4752                 GL_BlendFunc(GL_ONE, GL_ZERO);
4753                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4754                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4755                 GL_Color(1, 1, 1, 1);
4756                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4757                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4758
4759                 GL_BlendFunc(GL_ONE, GL_ONE);
4760                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4761                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4762                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4763                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4764                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4765                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4766                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4767
4768                 // copy the darkened bloom view to a texture
4769                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4770                 GL_ActiveTexture(0);
4771                 CHECKGLERROR
4772                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4773                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4774         }
4775 }
4776
4777 void R_HDR_RenderBloomTexture(void)
4778 {
4779         int oldwidth, oldheight;
4780         float oldcolorscale;
4781
4782         oldcolorscale = r_refdef.view.colorscale;
4783         oldwidth = r_refdef.view.width;
4784         oldheight = r_refdef.view.height;
4785         r_refdef.view.width = r_bloomstate.bloomwidth;
4786         r_refdef.view.height = r_bloomstate.bloomheight;
4787
4788         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
4789         // TODO: add exposure compensation features
4790         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4791
4792         r_refdef.view.showdebug = false;
4793         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4794
4795         R_ResetViewRendering3D();
4796
4797         R_ClearScreen(r_refdef.fogenabled);
4798         if (r_timereport_active)
4799                 R_TimeReport("HDRclear");
4800
4801         R_View_Update();
4802         if (r_timereport_active)
4803                 R_TimeReport("visibility");
4804
4805         // only do secondary renders with HDR if r_hdr is 2 or higher
4806         r_waterstate.numwaterplanes = 0;
4807         if (r_waterstate.enabled && r_hdr.integer >= 2)
4808                 R_RenderWaterPlanes();
4809
4810         r_refdef.view.showdebug = true;
4811         R_RenderScene();
4812         r_waterstate.numwaterplanes = 0;
4813
4814         R_ResetViewRendering2D();
4815
4816         R_Bloom_CopyHDRTexture();
4817         R_Bloom_MakeTexture();
4818
4819         // restore the view settings
4820         r_refdef.view.width = oldwidth;
4821         r_refdef.view.height = oldheight;
4822         r_refdef.view.colorscale = oldcolorscale;
4823
4824         R_ResetViewRendering3D();
4825
4826         R_ClearScreen(r_refdef.fogenabled);
4827         if (r_timereport_active)
4828                 R_TimeReport("viewclear");
4829 }
4830
4831 static void R_BlendView(void)
4832 {
4833         unsigned int permutation;
4834
4835         switch (vid.renderpath)
4836         {
4837         case RENDERPATH_GL20:
4838                 permutation =
4839                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4840                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4841                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4842                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4843                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4844
4845                 if (r_bloomstate.texture_screen)
4846                 {
4847                         // make sure the buffer is available
4848                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4849
4850                         R_ResetViewRendering2D();
4851                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4852                         R_Mesh_ColorPointer(NULL, 0, 0);
4853                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4854                         GL_ActiveTexture(0);CHECKGLERROR
4855
4856                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4857                         {
4858                                 // declare variables
4859                                 float speed;
4860                                 static float avgspeed;
4861
4862                                 speed = VectorLength(cl.movement_velocity);
4863
4864                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4865                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4866
4867                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4868                                 speed = bound(0, speed, 1);
4869                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4870
4871                                 // calculate values into a standard alpha
4872                                 cl.motionbluralpha = 1 - exp(-
4873                                                 (
4874                                                  (r_motionblur.value * speed / 80)
4875                                                  +
4876                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4877                                                 )
4878                                                 /
4879                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
4880                                            );
4881
4882                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4883                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4884                                 // apply the blur
4885                                 if (cl.motionbluralpha > 0)
4886                                 {
4887                                         R_SetupGenericShader(true);
4888                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4889                                         GL_Color(1, 1, 1, cl.motionbluralpha);
4890                                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4891                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4892                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4893                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4894                                 }
4895                         }
4896
4897                         // copy view into the screen texture
4898                         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4899                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4900                 }
4901                 else if (!r_bloomstate.texture_bloom)
4902                 {
4903                         // we may still have to do view tint...
4904                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4905                         {
4906                                 // apply a color tint to the whole view
4907                                 R_ResetViewRendering2D();
4908                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4909                                 R_Mesh_ColorPointer(NULL, 0, 0);
4910                                 R_SetupGenericShader(false);
4911                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4912                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4913                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4914                         }
4915                         break; // no screen processing, no bloom, skip it
4916                 }
4917
4918                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4919                 {
4920                         // render simple bloom effect
4921                         // copy the screen and shrink it and darken it for the bloom process
4922                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4923                         // make the bloom texture
4924                         R_Bloom_MakeTexture();
4925                 }
4926
4927                 R_ResetViewRendering2D();
4928                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4929                 R_Mesh_ColorPointer(NULL, 0, 0);
4930                 GL_Color(1, 1, 1, 1);
4931                 GL_BlendFunc(GL_ONE, GL_ZERO);
4932                 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4933                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4934                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4935                 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4936                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4937                 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4938                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4939                 if (r_glsl_permutation->loc_ViewTintColor >= 0)
4940                         qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4941                 if (r_glsl_permutation->loc_ClientTime >= 0)
4942                         qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4943                 if (r_glsl_permutation->loc_PixelSize >= 0)
4944                         qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4945                 if (r_glsl_permutation->loc_UserVec1 >= 0)
4946                 {
4947                         float a=0, b=0, c=0, d=0;
4948 #if _MSC_VER >= 1400
4949 #define sscanf sscanf_s
4950 #endif
4951                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4952                         qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4953                 }
4954                 if (r_glsl_permutation->loc_UserVec2 >= 0)
4955                 {
4956                         float a=0, b=0, c=0, d=0;
4957                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4958                         qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4959                 }
4960                 if (r_glsl_permutation->loc_UserVec3 >= 0)
4961                 {
4962                         float a=0, b=0, c=0, d=0;
4963                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4964                         qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4965                 }
4966                 if (r_glsl_permutation->loc_UserVec4 >= 0)
4967                 {
4968                         float a=0, b=0, c=0, d=0;
4969                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4970                         qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4971                 }
4972                 if (r_glsl_permutation->loc_Saturation >= 0)
4973                         qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4974                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4975                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4976                 break;
4977         case RENDERPATH_GL13:
4978         case RENDERPATH_GL11:
4979                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4980                 {
4981                         // apply a color tint to the whole view
4982                         R_ResetViewRendering2D();
4983                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4984                         R_Mesh_ColorPointer(NULL, 0, 0);
4985                         R_SetupGenericShader(false);
4986                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4987                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4988                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4989                 }
4990                 break;
4991         }
4992 }
4993
4994 matrix4x4_t r_waterscrollmatrix;
4995
4996 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4997 {
4998         if (r_refdef.fog_density)
4999         {
5000                 r_refdef.fogcolor[0] = r_refdef.fog_red;
5001                 r_refdef.fogcolor[1] = r_refdef.fog_green;
5002                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5003
5004                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5005                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5006                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5007                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5008
5009                 {
5010                         vec3_t fogvec;
5011                         VectorCopy(r_refdef.fogcolor, fogvec);
5012                         //   color.rgb *= ContrastBoost * SceneBrightness;
5013                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5014                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5015                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5016                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5017                 }
5018         }
5019 }
5020
5021 void R_UpdateVariables(void)
5022 {
5023         R_Textures_Frame();
5024
5025         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
5026
5027         r_refdef.farclip = r_farclip_base.value;
5028         if (r_refdef.scene.worldmodel)
5029                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5030         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5031
5032         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5033                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5034         r_refdef.polygonfactor = 0;
5035         r_refdef.polygonoffset = 0;
5036         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5037         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5038
5039         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5040         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5041         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5042         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5043         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5044         if (r_showsurfaces.integer)
5045         {
5046                 r_refdef.scene.rtworld = false;
5047                 r_refdef.scene.rtworldshadows = false;
5048                 r_refdef.scene.rtdlight = false;
5049                 r_refdef.scene.rtdlightshadows = false;
5050                 r_refdef.lightmapintensity = 0;
5051         }
5052
5053         if (gamemode == GAME_NEHAHRA)
5054         {
5055                 if (gl_fogenable.integer)
5056                 {
5057                         r_refdef.oldgl_fogenable = true;
5058                         r_refdef.fog_density = gl_fogdensity.value;
5059                         r_refdef.fog_red = gl_fogred.value;
5060                         r_refdef.fog_green = gl_foggreen.value;
5061                         r_refdef.fog_blue = gl_fogblue.value;
5062                         r_refdef.fog_alpha = 1;
5063                         r_refdef.fog_start = 0;
5064                         r_refdef.fog_end = gl_skyclip.value;
5065                         r_refdef.fog_height = 1<<30;
5066                         r_refdef.fog_fadedepth = 128;
5067                 }
5068                 else if (r_refdef.oldgl_fogenable)
5069                 {
5070                         r_refdef.oldgl_fogenable = false;
5071                         r_refdef.fog_density = 0;
5072                         r_refdef.fog_red = 0;
5073                         r_refdef.fog_green = 0;
5074                         r_refdef.fog_blue = 0;
5075                         r_refdef.fog_alpha = 0;
5076                         r_refdef.fog_start = 0;
5077                         r_refdef.fog_end = 0;
5078                         r_refdef.fog_height = 1<<30;
5079                         r_refdef.fog_fadedepth = 128;
5080                 }
5081         }
5082
5083         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5084         r_refdef.fog_start = max(0, r_refdef.fog_start);
5085         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5086
5087         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5088
5089         if (r_refdef.fog_density && r_drawfog.integer)
5090         {
5091                 r_refdef.fogenabled = true;
5092                 // this is the point where the fog reaches 0.9986 alpha, which we
5093                 // consider a good enough cutoff point for the texture
5094                 // (0.9986 * 256 == 255.6)
5095                 if (r_fog_exp2.integer)
5096                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5097                 else
5098                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5099                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5100                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5101                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5102                 // fog color was already set
5103                 // update the fog texture
5104                 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)
5105                         R_BuildFogTexture();
5106         }
5107         else
5108                 r_refdef.fogenabled = false;
5109
5110         switch(vid.renderpath)
5111         {
5112         case RENDERPATH_GL20:
5113                 if(v_glslgamma.integer && !vid_gammatables_trivial)
5114                 {
5115                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5116                         {
5117                                 // build GLSL gamma texture
5118 #define RAMPWIDTH 256
5119                                 unsigned short ramp[RAMPWIDTH * 3];
5120                                 unsigned char rampbgr[RAMPWIDTH][4];
5121                                 int i;
5122
5123                                 r_texture_gammaramps_serial = vid_gammatables_serial;
5124
5125                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5126                                 for(i = 0; i < RAMPWIDTH; ++i)
5127                                 {
5128                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5129                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5130                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5131                                         rampbgr[i][3] = 0;
5132                                 }
5133                                 if (r_texture_gammaramps)
5134                                 {
5135                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5136                                 }
5137                                 else
5138                                 {
5139                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
5140                                 }
5141                         }
5142                 }
5143                 else
5144                 {
5145                         // remove GLSL gamma texture
5146                 }
5147                 break;
5148         case RENDERPATH_GL13:
5149         case RENDERPATH_GL11:
5150                 break;
5151         }
5152 }
5153
5154 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5155 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5156 /*
5157 ================
5158 R_SelectScene
5159 ================
5160 */
5161 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5162         if( scenetype != r_currentscenetype ) {
5163                 // store the old scenetype
5164                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5165                 r_currentscenetype = scenetype;
5166                 // move in the new scene
5167                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5168         }
5169 }
5170
5171 /*
5172 ================
5173 R_GetScenePointer
5174 ================
5175 */
5176 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5177 {
5178         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5179         if( scenetype == r_currentscenetype ) {
5180                 return &r_refdef.scene;
5181         } else {
5182                 return &r_scenes_store[ scenetype ];
5183         }
5184 }
5185
5186 /*
5187 ================
5188 R_RenderView
5189 ================
5190 */
5191 void R_RenderView(void)
5192 {
5193         if (r_timereport_active)
5194                 R_TimeReport("start");
5195         r_frame++; // used only by R_GetCurrentTexture
5196         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5197
5198         if (!r_drawentities.integer)
5199                 r_refdef.scene.numentities = 0;
5200
5201         R_AnimCache_ClearCache();
5202         R_FrameData_NewFrame();
5203
5204         if (r_refdef.view.isoverlay)
5205         {
5206                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5207                 GL_Clear( GL_DEPTH_BUFFER_BIT );
5208                 R_TimeReport("depthclear");
5209
5210                 r_refdef.view.showdebug = false;
5211
5212                 r_waterstate.enabled = false;
5213                 r_waterstate.numwaterplanes = 0;
5214
5215                 R_RenderScene();
5216
5217                 CHECKGLERROR
5218                 return;
5219         }
5220
5221         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
5222                 return; //Host_Error ("R_RenderView: NULL worldmodel");
5223
5224         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
5225
5226         // break apart the view matrix into vectors for various purposes
5227         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5228         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5229         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5230         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5231         // make an inverted copy of the view matrix for tracking sprites
5232         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5233
5234         R_Shadow_UpdateWorldLightSelection();
5235
5236         R_Bloom_StartFrame();
5237         R_Water_StartFrame();
5238
5239         CHECKGLERROR
5240         if (r_timereport_active)
5241                 R_TimeReport("viewsetup");
5242
5243         R_ResetViewRendering3D();
5244
5245         if (r_refdef.view.clear || r_refdef.fogenabled)
5246         {
5247                 R_ClearScreen(r_refdef.fogenabled);
5248                 if (r_timereport_active)
5249                         R_TimeReport("viewclear");
5250         }
5251         r_refdef.view.clear = true;
5252
5253         // this produces a bloom texture to be used in R_BlendView() later
5254         if (r_hdr.integer && r_bloomstate.bloomwidth)
5255                 R_HDR_RenderBloomTexture();
5256
5257         r_refdef.view.showdebug = true;
5258
5259         R_View_Update();
5260         if (r_timereport_active)
5261                 R_TimeReport("visibility");
5262
5263         r_waterstate.numwaterplanes = 0;
5264         if (r_waterstate.enabled)
5265                 R_RenderWaterPlanes();
5266
5267         R_RenderScene();
5268         r_waterstate.numwaterplanes = 0;
5269
5270         R_BlendView();
5271         if (r_timereport_active)
5272                 R_TimeReport("blendview");
5273
5274         GL_Scissor(0, 0, vid.width, vid.height);
5275         GL_ScissorTest(false);
5276         CHECKGLERROR
5277 }
5278
5279 void R_RenderWaterPlanes(void)
5280 {
5281         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5282         {
5283                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5284                 if (r_timereport_active)
5285                         R_TimeReport("waterworld");
5286         }
5287
5288         // don't let sound skip if going slow
5289         if (r_refdef.scene.extraupdate)
5290                 S_ExtraUpdate ();
5291
5292         R_DrawModelsAddWaterPlanes();
5293         if (r_timereport_active)
5294                 R_TimeReport("watermodels");
5295
5296         if (r_waterstate.numwaterplanes)
5297         {
5298                 R_Water_ProcessPlanes();
5299                 if (r_timereport_active)
5300                         R_TimeReport("waterscenes");
5301         }
5302 }
5303
5304 extern void R_DrawLightningBeams (void);
5305 extern void VM_CL_AddPolygonsToMeshQueue (void);
5306 extern void R_DrawPortals (void);
5307 extern cvar_t cl_locs_show;
5308 static void R_DrawLocs(void);
5309 static void R_DrawEntityBBoxes(void);
5310 static void R_DrawModelDecals(void);
5311 extern cvar_t cl_decals_newsystem;
5312 extern qboolean r_shadow_usingdeferredprepass;
5313 void R_RenderScene(void)
5314 {
5315         r_refdef.stats.renders++;
5316
5317         R_UpdateFogColor();
5318
5319         // don't let sound skip if going slow
5320         if (r_refdef.scene.extraupdate)
5321                 S_ExtraUpdate ();
5322
5323         R_MeshQueue_BeginScene();
5324
5325         R_SkyStartFrame();
5326
5327         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);
5328
5329         if (cl.csqc_vidvars.drawworld)
5330         {
5331                 // don't let sound skip if going slow
5332                 if (r_refdef.scene.extraupdate)
5333                         S_ExtraUpdate ();
5334
5335                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5336                 {
5337                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5338                         if (r_timereport_active)
5339                                 R_TimeReport("worldsky");
5340                 }
5341
5342                 if (R_DrawBrushModelsSky() && r_timereport_active)
5343                         R_TimeReport("bmodelsky");
5344
5345                 if (skyrendermasked && skyrenderlater)
5346                 {
5347                         // we have to force off the water clipping plane while rendering sky
5348                         R_SetupView(false);
5349                         R_Sky();
5350                         R_SetupView(true);
5351                         if (r_timereport_active)
5352                                 R_TimeReport("sky");
5353                 }
5354         }
5355
5356         R_AnimCache_CacheVisibleEntities();
5357         if (r_timereport_active)
5358                 R_TimeReport("animation");
5359
5360         R_Shadow_PrepareLights();
5361         if (r_timereport_active)
5362                 R_TimeReport("preparelights");
5363
5364         if (r_shadow_usingdeferredprepass)
5365                 R_Shadow_DrawPrepass();
5366
5367         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5368         {
5369                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5370                 if (r_timereport_active)
5371                         R_TimeReport("worlddepth");
5372         }
5373         if (r_depthfirst.integer >= 2)
5374         {
5375                 R_DrawModelsDepth();
5376                 if (r_timereport_active)
5377                         R_TimeReport("modeldepth");
5378         }
5379
5380         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5381         {
5382                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5383                 if (r_timereport_active)
5384                         R_TimeReport("world");
5385         }
5386
5387         // don't let sound skip if going slow
5388         if (r_refdef.scene.extraupdate)
5389                 S_ExtraUpdate ();
5390
5391         R_DrawModels();
5392         if (r_timereport_active)
5393                 R_TimeReport("models");
5394
5395         // don't let sound skip if going slow
5396         if (r_refdef.scene.extraupdate)
5397                 S_ExtraUpdate ();
5398
5399         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5400         {
5401                 R_DrawModelShadows();
5402                 R_ResetViewRendering3D();
5403                 // don't let sound skip if going slow
5404                 if (r_refdef.scene.extraupdate)
5405                         S_ExtraUpdate ();
5406         }
5407
5408         if (!r_shadow_usingdeferredprepass)
5409         {
5410                 R_Shadow_DrawLights();
5411                 if (r_timereport_active)
5412                         R_TimeReport("rtlights");
5413         }
5414
5415         // don't let sound skip if going slow
5416         if (r_refdef.scene.extraupdate)
5417                 S_ExtraUpdate ();
5418
5419         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5420         {
5421                 R_DrawModelShadows();
5422                 R_ResetViewRendering3D();
5423                 // don't let sound skip if going slow
5424                 if (r_refdef.scene.extraupdate)
5425                         S_ExtraUpdate ();
5426         }
5427
5428         if (cl.csqc_vidvars.drawworld)
5429         {
5430                 if (cl_decals_newsystem.integer)
5431                 {
5432                         R_DrawModelDecals();
5433                         if (r_timereport_active)
5434                                 R_TimeReport("modeldecals");
5435                 }
5436                 else
5437                 {
5438                         R_DrawDecals();
5439                         if (r_timereport_active)
5440                                 R_TimeReport("decals");
5441                 }
5442
5443                 R_DrawParticles();
5444                 if (r_timereport_active)
5445                         R_TimeReport("particles");
5446
5447                 R_DrawExplosions();
5448                 if (r_timereport_active)
5449                         R_TimeReport("explosions");
5450
5451                 R_DrawLightningBeams();
5452                 if (r_timereport_active)
5453                         R_TimeReport("lightning");
5454         }
5455
5456         R_SetupGenericShader(true);
5457         VM_CL_AddPolygonsToMeshQueue();
5458
5459         if (r_refdef.view.showdebug)
5460         {
5461                 if (cl_locs_show.integer)
5462                 {
5463                         R_DrawLocs();
5464                         if (r_timereport_active)
5465                                 R_TimeReport("showlocs");
5466                 }
5467
5468                 if (r_drawportals.integer)
5469                 {
5470                         R_DrawPortals();
5471                         if (r_timereport_active)
5472                                 R_TimeReport("portals");
5473                 }
5474
5475                 if (r_showbboxes.value > 0)
5476                 {
5477                         R_DrawEntityBBoxes();
5478                         if (r_timereport_active)
5479                                 R_TimeReport("bboxes");
5480                 }
5481         }
5482
5483         R_SetupGenericShader(true);
5484         R_MeshQueue_RenderTransparent();
5485         if (r_timereport_active)
5486                 R_TimeReport("drawtrans");
5487
5488         R_SetupGenericShader(true);
5489
5490         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))
5491         {
5492                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5493                 if (r_timereport_active)
5494                         R_TimeReport("worlddebug");
5495                 R_DrawModelsDebug();
5496                 if (r_timereport_active)
5497                         R_TimeReport("modeldebug");
5498         }
5499
5500         R_SetupGenericShader(true);
5501
5502         if (cl.csqc_vidvars.drawworld)
5503         {
5504                 R_Shadow_DrawCoronas();
5505                 if (r_timereport_active)
5506                         R_TimeReport("coronas");
5507         }
5508
5509         // don't let sound skip if going slow
5510         if (r_refdef.scene.extraupdate)
5511                 S_ExtraUpdate ();
5512
5513         R_ResetViewRendering2D();
5514 }
5515
5516 static const unsigned short bboxelements[36] =
5517 {
5518         5, 1, 3, 5, 3, 7,
5519         6, 2, 0, 6, 0, 4,
5520         7, 3, 2, 7, 2, 6,
5521         4, 0, 1, 4, 1, 5,
5522         4, 5, 7, 4, 7, 6,
5523         1, 0, 2, 1, 2, 3,
5524 };
5525
5526 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5527 {
5528         int i;
5529         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5530
5531         RSurf_ActiveWorldEntity();
5532
5533         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5534         GL_DepthMask(false);
5535         GL_DepthRange(0, 1);
5536         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5537         R_Mesh_ResetTextureState();
5538
5539         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5540         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5541         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5542         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5543         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5544         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5545         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5546         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5547         R_FillColors(color4f, 8, cr, cg, cb, ca);
5548         if (r_refdef.fogenabled)
5549         {
5550                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5551                 {
5552                         f1 = RSurf_FogVertex(v);
5553                         f2 = 1 - f1;
5554                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5555                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5556                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5557                 }
5558         }
5559         R_Mesh_VertexPointer(vertex3f, 0, 0);
5560         R_Mesh_ColorPointer(color4f, 0, 0);
5561         R_Mesh_ResetTextureState();
5562         R_SetupGenericShader(false);
5563         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5564 }
5565
5566 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5567 {
5568         int i;
5569         float color[4];
5570         prvm_edict_t *edict;
5571         prvm_prog_t *prog_save = prog;
5572
5573         // this function draws bounding boxes of server entities
5574         if (!sv.active)
5575                 return;
5576
5577         GL_CullFace(GL_NONE);
5578         R_SetupGenericShader(false);
5579
5580         prog = 0;
5581         SV_VM_Begin();
5582         for (i = 0;i < numsurfaces;i++)
5583         {
5584                 edict = PRVM_EDICT_NUM(surfacelist[i]);
5585                 switch ((int)edict->fields.server->solid)
5586                 {
5587                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
5588                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
5589                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
5590                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5591                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
5592                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
5593                 }
5594                 color[3] *= r_showbboxes.value;
5595                 color[3] = bound(0, color[3], 1);
5596                 GL_DepthTest(!r_showdisabledepthtest.integer);
5597                 GL_CullFace(r_refdef.view.cullface_front);
5598                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5599         }
5600         SV_VM_End();
5601         prog = prog_save;
5602 }
5603
5604 static void R_DrawEntityBBoxes(void)
5605 {
5606         int i;
5607         prvm_edict_t *edict;
5608         vec3_t center;
5609         prvm_prog_t *prog_save = prog;
5610
5611         // this function draws bounding boxes of server entities
5612         if (!sv.active)
5613                 return;
5614
5615         prog = 0;
5616         SV_VM_Begin();
5617         for (i = 0;i < prog->num_edicts;i++)
5618         {
5619                 edict = PRVM_EDICT_NUM(i);
5620                 if (edict->priv.server->free)
5621                         continue;
5622                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5623                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5624                         continue;
5625                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5626                         continue;
5627                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5628                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5629         }
5630         SV_VM_End();
5631         prog = prog_save;
5632 }
5633
5634 static const int nomodelelement3i[24] =
5635 {
5636         5, 2, 0,
5637         5, 1, 2,
5638         5, 0, 3,
5639         5, 3, 1,
5640         0, 2, 4,
5641         2, 1, 4,
5642         3, 0, 4,
5643         1, 3, 4
5644 };
5645
5646 static const unsigned short nomodelelement3s[24] =
5647 {
5648         5, 2, 0,
5649         5, 1, 2,
5650         5, 0, 3,
5651         5, 3, 1,
5652         0, 2, 4,
5653         2, 1, 4,
5654         3, 0, 4,
5655         1, 3, 4
5656 };
5657
5658 static const float nomodelvertex3f[6*3] =
5659 {
5660         -16,   0,   0,
5661          16,   0,   0,
5662           0, -16,   0,
5663           0,  16,   0,
5664           0,   0, -16,
5665           0,   0,  16
5666 };
5667
5668 static const float nomodelcolor4f[6*4] =
5669 {
5670         0.0f, 0.0f, 0.5f, 1.0f,
5671         0.0f, 0.0f, 0.5f, 1.0f,
5672         0.0f, 0.5f, 0.0f, 1.0f,
5673         0.0f, 0.5f, 0.0f, 1.0f,
5674         0.5f, 0.0f, 0.0f, 1.0f,
5675         0.5f, 0.0f, 0.0f, 1.0f
5676 };
5677
5678 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5679 {
5680         int i;
5681         float f1, f2, *c;
5682         float color4f[6*4];
5683
5684         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);
5685
5686         // this is only called once per entity so numsurfaces is always 1, and
5687         // surfacelist is always {0}, so this code does not handle batches
5688
5689         if (rsurface.ent_flags & RENDER_ADDITIVE)
5690         {
5691                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5692                 GL_DepthMask(false);
5693         }
5694         else if (rsurface.colormod[3] < 1)
5695         {
5696                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5697                 GL_DepthMask(false);
5698         }
5699         else
5700         {
5701                 GL_BlendFunc(GL_ONE, GL_ZERO);
5702                 GL_DepthMask(true);
5703         }
5704         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5705         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5706         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5707         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5708         R_SetupGenericShader(false);
5709         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5710         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5711         R_Mesh_ColorPointer(color4f, 0, 0);
5712         for (i = 0, c = color4f;i < 6;i++, c += 4)
5713         {
5714                 c[0] *= rsurface.colormod[0];
5715                 c[1] *= rsurface.colormod[1];
5716                 c[2] *= rsurface.colormod[2];
5717                 c[3] *= rsurface.colormod[3];
5718         }
5719         if (r_refdef.fogenabled)
5720         {
5721                 for (i = 0, c = color4f;i < 6;i++, c += 4)
5722                 {
5723                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5724                         f2 = 1 - f1;
5725                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5726                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5727                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5728                 }
5729         }
5730         R_Mesh_ResetTextureState();
5731         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5732 }
5733
5734 void R_DrawNoModel(entity_render_t *ent)
5735 {
5736         vec3_t org;
5737         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5738         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5739                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5740         else
5741                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5742 }
5743
5744 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5745 {
5746         vec3_t right1, right2, diff, normal;
5747
5748         VectorSubtract (org2, org1, normal);
5749
5750         // calculate 'right' vector for start
5751         VectorSubtract (r_refdef.view.origin, org1, diff);
5752         CrossProduct (normal, diff, right1);
5753         VectorNormalize (right1);
5754
5755         // calculate 'right' vector for end
5756         VectorSubtract (r_refdef.view.origin, org2, diff);
5757         CrossProduct (normal, diff, right2);
5758         VectorNormalize (right2);
5759
5760         vert[ 0] = org1[0] + width * right1[0];
5761         vert[ 1] = org1[1] + width * right1[1];
5762         vert[ 2] = org1[2] + width * right1[2];
5763         vert[ 3] = org1[0] - width * right1[0];
5764         vert[ 4] = org1[1] - width * right1[1];
5765         vert[ 5] = org1[2] - width * right1[2];
5766         vert[ 6] = org2[0] - width * right2[0];
5767         vert[ 7] = org2[1] - width * right2[1];
5768         vert[ 8] = org2[2] - width * right2[2];
5769         vert[ 9] = org2[0] + width * right2[0];
5770         vert[10] = org2[1] + width * right2[1];
5771         vert[11] = org2[2] + width * right2[2];
5772 }
5773
5774 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)
5775 {
5776         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5777         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5778         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5779         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5780         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5781         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5782         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5783         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5784         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5785         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5786         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5787         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5788 }
5789
5790 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5791 {
5792         int i;
5793         float *vertex3f;
5794         float v[3];
5795         VectorSet(v, x, y, z);
5796         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5797                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5798                         break;
5799         if (i == mesh->numvertices)
5800         {
5801                 if (mesh->numvertices < mesh->maxvertices)
5802                 {
5803                         VectorCopy(v, vertex3f);
5804                         mesh->numvertices++;
5805                 }
5806                 return mesh->numvertices;
5807         }
5808         else
5809                 return i;
5810 }
5811
5812 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5813 {
5814         int i;
5815         int *e, element[3];
5816         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5817         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5818         e = mesh->element3i + mesh->numtriangles * 3;
5819         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5820         {
5821                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5822                 if (mesh->numtriangles < mesh->maxtriangles)
5823                 {
5824                         *e++ = element[0];
5825                         *e++ = element[1];
5826                         *e++ = element[2];
5827                         mesh->numtriangles++;
5828                 }
5829                 element[1] = element[2];
5830         }
5831 }
5832
5833 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5834 {
5835         int i;
5836         int *e, element[3];
5837         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5838         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5839         e = mesh->element3i + mesh->numtriangles * 3;
5840         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5841         {
5842                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5843                 if (mesh->numtriangles < mesh->maxtriangles)
5844                 {
5845                         *e++ = element[0];
5846                         *e++ = element[1];
5847                         *e++ = element[2];
5848                         mesh->numtriangles++;
5849                 }
5850                 element[1] = element[2];
5851         }
5852 }
5853
5854 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5855 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5856 {
5857         int planenum, planenum2;
5858         int w;
5859         int tempnumpoints;
5860         mplane_t *plane, *plane2;
5861         double maxdist;
5862         double temppoints[2][256*3];
5863         // figure out how large a bounding box we need to properly compute this brush
5864         maxdist = 0;
5865         for (w = 0;w < numplanes;w++)
5866                 maxdist = max(maxdist, fabs(planes[w].dist));
5867         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5868         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5869         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5870         {
5871                 w = 0;
5872                 tempnumpoints = 4;
5873                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5874                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5875                 {
5876                         if (planenum2 == planenum)
5877                                 continue;
5878                         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);
5879                         w = !w;
5880                 }
5881                 if (tempnumpoints < 3)
5882                         continue;
5883                 // generate elements forming a triangle fan for this polygon
5884                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5885         }
5886 }
5887
5888 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)
5889 {
5890         texturelayer_t *layer;
5891         layer = t->currentlayers + t->currentnumlayers++;
5892         layer->type = type;
5893         layer->depthmask = depthmask;
5894         layer->blendfunc1 = blendfunc1;
5895         layer->blendfunc2 = blendfunc2;
5896         layer->texture = texture;
5897         layer->texmatrix = *matrix;
5898         layer->color[0] = r;
5899         layer->color[1] = g;
5900         layer->color[2] = b;
5901         layer->color[3] = a;
5902 }
5903
5904 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5905 {
5906         double index, f;
5907         index = parms[2] + r_refdef.scene.time * parms[3];
5908         index -= floor(index);
5909         switch (func)
5910         {
5911         default:
5912         case Q3WAVEFUNC_NONE:
5913         case Q3WAVEFUNC_NOISE:
5914         case Q3WAVEFUNC_COUNT:
5915                 f = 0;
5916                 break;
5917         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5918         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5919         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5920         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5921         case Q3WAVEFUNC_TRIANGLE:
5922                 index *= 4;
5923                 f = index - floor(index);
5924                 if (index < 1)
5925                         f = f;
5926                 else if (index < 2)
5927                         f = 1 - f;
5928                 else if (index < 3)
5929                         f = -f;
5930                 else
5931                         f = -(1 - f);
5932                 break;
5933         }
5934         return (float)(parms[0] + parms[1] * f);
5935 }
5936
5937 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5938 {
5939         int w, h, idx;
5940         float f;
5941         float tcmat[12];
5942         matrix4x4_t matrix, temp;
5943         switch(tcmod->tcmod)
5944         {
5945                 case Q3TCMOD_COUNT:
5946                 case Q3TCMOD_NONE:
5947                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5948                                 matrix = r_waterscrollmatrix;
5949                         else
5950                                 matrix = identitymatrix;
5951                         break;
5952                 case Q3TCMOD_ENTITYTRANSLATE:
5953                         // this is used in Q3 to allow the gamecode to control texcoord
5954                         // scrolling on the entity, which is not supported in darkplaces yet.
5955                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5956                         break;
5957                 case Q3TCMOD_ROTATE:
5958                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5959                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5960                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5961                         break;
5962                 case Q3TCMOD_SCALE:
5963                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5964                         break;
5965                 case Q3TCMOD_SCROLL:
5966                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5967                         break;
5968                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5969                         w = (int) tcmod->parms[0];
5970                         h = (int) tcmod->parms[1];
5971                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5972                         f = f - floor(f);
5973                         idx = (int) floor(f * w * h);
5974                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5975                         break;
5976                 case Q3TCMOD_STRETCH:
5977                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5978                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5979                         break;
5980                 case Q3TCMOD_TRANSFORM:
5981                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
5982                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
5983                         VectorSet(tcmat +  6, 0                   , 0                , 1);
5984                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
5985                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5986                         break;
5987                 case Q3TCMOD_TURBULENT:
5988                         // this is handled in the RSurf_PrepareVertices function
5989                         matrix = identitymatrix;
5990                         break;
5991         }
5992         temp = *texmatrix;
5993         Matrix4x4_Concat(texmatrix, &matrix, &temp);
5994 }
5995
5996 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5997 {
5998         int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5999         char name[MAX_QPATH];
6000         skinframe_t *skinframe;
6001         unsigned char pixels[296*194];
6002         strlcpy(cache->name, skinname, sizeof(cache->name));
6003         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6004         if (developer_loading.integer)
6005                 Con_Printf("loading %s\n", name);
6006         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6007         if (!skinframe || !skinframe->base)
6008         {
6009                 unsigned char *f;
6010                 fs_offset_t filesize;
6011                 skinframe = NULL;
6012                 f = FS_LoadFile(name, tempmempool, true, &filesize);
6013                 if (f)
6014                 {
6015                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
6016                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6017                         Mem_Free(f);
6018                 }
6019         }
6020         cache->skinframe = skinframe;
6021 }
6022
6023 texture_t *R_GetCurrentTexture(texture_t *t)
6024 {
6025         int i;
6026         const entity_render_t *ent = rsurface.entity;
6027         dp_model_t *model = ent->model;
6028         q3shaderinfo_layer_tcmod_t *tcmod;
6029
6030         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
6031                 return t->currentframe;
6032         t->update_lastrenderframe = r_frame;
6033         t->update_lastrenderentity = (void *)ent;
6034
6035         // switch to an alternate material if this is a q1bsp animated material
6036         {
6037                 texture_t *texture = t;
6038                 int s = rsurface.ent_skinnum;
6039                 if ((unsigned int)s >= (unsigned int)model->numskins)
6040                         s = 0;
6041                 if (model->skinscenes)
6042                 {
6043                         if (model->skinscenes[s].framecount > 1)
6044                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6045                         else
6046                                 s = model->skinscenes[s].firstframe;
6047                 }
6048                 if (s > 0)
6049                         t = t + s * model->num_surfaces;
6050                 if (t->animated)
6051                 {
6052                         // use an alternate animation if the entity's frame is not 0,
6053                         // and only if the texture has an alternate animation
6054                         if (rsurface.ent_alttextures && t->anim_total[1])
6055                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6056                         else
6057                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6058                 }
6059                 texture->currentframe = t;
6060         }
6061
6062         // update currentskinframe to be a qw skin or animation frame
6063         if (rsurface.ent_qwskin >= 0)
6064         {
6065                 i = rsurface.ent_qwskin;
6066                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6067                 {
6068                         r_qwskincache_size = cl.maxclients;
6069                         if (r_qwskincache)
6070                                 Mem_Free(r_qwskincache);
6071                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6072                 }
6073                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6074                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6075                 t->currentskinframe = r_qwskincache[i].skinframe;
6076                 if (t->currentskinframe == NULL)
6077                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6078         }
6079         else if (t->numskinframes >= 2)
6080                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6081         if (t->backgroundnumskinframes >= 2)
6082                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6083
6084         t->currentmaterialflags = t->basematerialflags;
6085         t->currentalpha = rsurface.colormod[3];
6086         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6087                 t->currentalpha *= r_wateralpha.value;
6088         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6089                 t->currentalpha *= t->r_water_wateralpha;
6090         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6091                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6092         if (!(rsurface.ent_flags & RENDER_LIGHT))
6093                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6094         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6095         {
6096                 // pick a model lighting mode
6097                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6098                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6099                 else
6100                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6101         }
6102         if (rsurface.ent_flags & RENDER_ADDITIVE)
6103                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6104         else if (t->currentalpha < 1)
6105                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6106         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6107                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6108         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6109                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6110         if (t->backgroundnumskinframes)
6111                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6112         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6113         {
6114                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6115                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6116         }
6117         else
6118                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6119         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6120                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6121
6122         // there is no tcmod
6123         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6124         {
6125                 t->currenttexmatrix = r_waterscrollmatrix;
6126                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6127         }
6128         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6129         {
6130                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6131                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6132         }
6133
6134         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6135                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6136         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6137                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6138
6139         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6140         if (t->currentskinframe->qpixels)
6141                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6142         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6143         t->glosstexture = r_texture_black;
6144         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6145         t->backgroundglosstexture = r_texture_black;
6146         t->specularpower = r_shadow_glossexponent.value;
6147         // TODO: store reference values for these in the texture?
6148         t->specularscale = 0;
6149         if (r_shadow_gloss.integer > 0)
6150         {
6151                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6152                 {
6153                         if (r_shadow_glossintensity.value > 0)
6154                         {
6155                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6156                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6157                                 t->specularscale = r_shadow_glossintensity.value;
6158                         }
6159                 }
6160                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6161                 {
6162                         t->glosstexture = r_texture_white;
6163                         t->backgroundglosstexture = r_texture_white;
6164                         t->specularscale = r_shadow_gloss2intensity.value;
6165                         t->specularpower = r_shadow_gloss2exponent.value;
6166                 }
6167         }
6168         t->specularscale *= t->specularscalemod;
6169         t->specularpower *= t->specularpowermod;
6170
6171         // lightmaps mode looks bad with dlights using actual texturing, so turn
6172         // off the colormap and glossmap, but leave the normalmap on as it still
6173         // accurately represents the shading involved
6174         if (gl_lightmaps.integer)
6175         {
6176                 t->basetexture = r_texture_grey128;
6177                 t->backgroundbasetexture = NULL;
6178                 t->specularscale = 0;
6179                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6180         }
6181
6182         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
6183         VectorClear(t->dlightcolor);
6184         t->currentnumlayers = 0;
6185         if (t->currentmaterialflags & MATERIALFLAG_WALL)
6186         {
6187                 int blendfunc1, blendfunc2;
6188                 qboolean depthmask;
6189                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6190                 {
6191                         blendfunc1 = GL_SRC_ALPHA;
6192                         blendfunc2 = GL_ONE;
6193                 }
6194                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6195                 {
6196                         blendfunc1 = GL_SRC_ALPHA;
6197                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6198                 }
6199                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6200                 {
6201                         blendfunc1 = t->customblendfunc[0];
6202                         blendfunc2 = t->customblendfunc[1];
6203                 }
6204                 else
6205                 {
6206                         blendfunc1 = GL_ONE;
6207                         blendfunc2 = GL_ZERO;
6208                 }
6209                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
6210                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6211                 {
6212                         // fullbright is not affected by r_refdef.lightmapintensity
6213                         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]);
6214                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6215                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &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]);
6216                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6217                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &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]);
6218                 }
6219                 else
6220                 {
6221                         vec3_t ambientcolor;
6222                         float colorscale;
6223                         // set the color tint used for lights affecting this surface
6224                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
6225                         colorscale = 2;
6226                         // q3bsp has no lightmap updates, so the lightstylevalue that
6227                         // would normally be baked into the lightmap must be
6228                         // applied to the color
6229                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
6230                         if (model->type == mod_brushq3)
6231                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
6232                         colorscale *= r_refdef.lightmapintensity;
6233                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
6234                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
6235                         // basic lit geometry
6236                         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]);
6237                         // add pants/shirt if needed
6238                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6239                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &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]);
6240                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6241                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &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]);
6242                         // now add ambient passes if needed
6243                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
6244                         {
6245                                 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]);
6246                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6247                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
6248                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6249                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
6250                         }
6251                 }
6252                 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
6253                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
6254                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
6255                 {
6256                         // if this is opaque use alpha blend which will darken the earlier
6257                         // passes cheaply.
6258                         //
6259                         // if this is an alpha blended material, all the earlier passes
6260                         // were darkened by fog already, so we only need to add the fog
6261                         // color ontop through the fog mask texture
6262                         //
6263                         // if this is an additive blended material, all the earlier passes
6264                         // were darkened by fog already, and we should not add fog color
6265                         // (because the background was not darkened, there is no fog color
6266                         // that was lost behind it).
6267                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &t->currenttexmatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]);
6268                 }
6269         }
6270
6271         return t->currentframe;
6272 }
6273
6274 rsurfacestate_t rsurface;
6275
6276 void R_Mesh_ResizeArrays(int newvertices)
6277 {
6278         float *base;
6279         if (rsurface.array_size >= newvertices)
6280                 return;
6281         if (rsurface.array_modelvertex3f)
6282                 Mem_Free(rsurface.array_modelvertex3f);
6283         rsurface.array_size = (newvertices + 1023) & ~1023;
6284         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6285         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
6286         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
6287         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
6288         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
6289         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
6290         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6291         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6292         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
6293         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
6294         rsurface.array_color4f           = base + rsurface.array_size * 27;
6295         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6296 }
6297
6298 void RSurf_ActiveWorldEntity(void)
6299 {
6300         dp_model_t *model = r_refdef.scene.worldmodel;
6301         //if (rsurface.entity == r_refdef.scene.worldentity)
6302         //      return;
6303         rsurface.entity = r_refdef.scene.worldentity;
6304         rsurface.skeleton = NULL;
6305         rsurface.ent_skinnum = 0;
6306         rsurface.ent_qwskin = -1;
6307         rsurface.ent_shadertime = 0;
6308         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6309         if (rsurface.array_size < model->surfmesh.num_vertices)
6310                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6311         rsurface.matrix = identitymatrix;
6312         rsurface.inversematrix = identitymatrix;
6313         rsurface.matrixscale = 1;
6314         rsurface.inversematrixscale = 1;
6315         R_Mesh_Matrix(&identitymatrix);
6316         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6317         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6318         rsurface.fograngerecip = r_refdef.fograngerecip;
6319         rsurface.fogheightfade = r_refdef.fogheightfade;
6320         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6321         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6322         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6323         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6324         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6325         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6326         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6327         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
6328         rsurface.colormod[3] = 1;
6329         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);
6330         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6331         rsurface.frameblend[0].lerp = 1;
6332         rsurface.ent_alttextures = false;
6333         rsurface.basepolygonfactor = r_refdef.polygonfactor;
6334         rsurface.basepolygonoffset = r_refdef.polygonoffset;
6335         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
6336         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6337         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6338         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6339         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6340         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6341         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6342         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6343         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6344         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
6345         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6346         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6347         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
6348         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6349         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6350         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
6351         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6352         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6353         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
6354         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6355         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6356         rsurface.modelelement3i = model->surfmesh.data_element3i;
6357         rsurface.modelelement3s = model->surfmesh.data_element3s;
6358         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6359         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6360         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6361         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6362         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6363         rsurface.modelsurfaces = model->data_surfaces;
6364         rsurface.generatedvertex = false;
6365         rsurface.vertex3f  = rsurface.modelvertex3f;
6366         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6367         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6368         rsurface.svector3f = rsurface.modelsvector3f;
6369         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6370         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6371         rsurface.tvector3f = rsurface.modeltvector3f;
6372         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6373         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6374         rsurface.normal3f  = rsurface.modelnormal3f;
6375         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6376         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6377         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6378 }
6379
6380 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
6381 {
6382         dp_model_t *model = ent->model;
6383         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6384         //      return;
6385         rsurface.entity = (entity_render_t *)ent;
6386         rsurface.skeleton = ent->skeleton;
6387         rsurface.ent_skinnum = ent->skinnum;
6388         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;
6389         rsurface.ent_shadertime = ent->shadertime;
6390         rsurface.ent_flags = ent->flags;
6391         if (rsurface.array_size < model->surfmesh.num_vertices)
6392                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6393         rsurface.matrix = ent->matrix;
6394         rsurface.inversematrix = ent->inversematrix;
6395         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6396         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6397         R_Mesh_Matrix(&rsurface.matrix);
6398         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6399         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6400         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6401         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6402         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6403         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6404         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6405         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6406         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6407         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6408         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6409         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
6410         rsurface.colormod[3] = ent->alpha;
6411         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
6412         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6413         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6414         rsurface.basepolygonfactor = r_refdef.polygonfactor;
6415         rsurface.basepolygonoffset = r_refdef.polygonoffset;
6416         if (ent->model->brush.submodel && !prepass)
6417         {
6418                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6419                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6420         }
6421         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6422         {
6423                 if (ent->animcache_vertex3f && !r_framedata_failed)
6424                 {
6425                         rsurface.modelvertex3f = ent->animcache_vertex3f;
6426                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
6427                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
6428                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
6429                 }
6430                 else if (wanttangents)
6431                 {
6432                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6433                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6434                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6435                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6436                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6437                 }
6438                 else if (wantnormals)
6439                 {
6440                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6441                         rsurface.modelsvector3f = NULL;
6442                         rsurface.modeltvector3f = NULL;
6443                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6444                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6445                 }
6446                 else
6447                 {
6448                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6449                         rsurface.modelsvector3f = NULL;
6450                         rsurface.modeltvector3f = NULL;
6451                         rsurface.modelnormal3f = NULL;
6452                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6453                 }
6454                 rsurface.modelvertex3f_bufferobject = 0;
6455                 rsurface.modelvertex3f_bufferoffset = 0;
6456                 rsurface.modelsvector3f_bufferobject = 0;
6457                 rsurface.modelsvector3f_bufferoffset = 0;
6458                 rsurface.modeltvector3f_bufferobject = 0;
6459                 rsurface.modeltvector3f_bufferoffset = 0;
6460                 rsurface.modelnormal3f_bufferobject = 0;
6461                 rsurface.modelnormal3f_bufferoffset = 0;
6462                 rsurface.generatedvertex = true;
6463         }
6464         else
6465         {
6466                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
6467                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6468                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6469                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6470                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6471                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6472                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6473                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6474                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6475                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
6476                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6477                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6478                 rsurface.generatedvertex = false;
6479         }
6480         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
6481         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6482         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6483         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
6484         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6485         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6486         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
6487         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6488         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6489         rsurface.modelelement3i = model->surfmesh.data_element3i;
6490         rsurface.modelelement3s = model->surfmesh.data_element3s;
6491         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6492         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6493         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6494         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6495         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6496         rsurface.modelsurfaces = model->data_surfaces;
6497         rsurface.vertex3f  = rsurface.modelvertex3f;
6498         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6499         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6500         rsurface.svector3f = rsurface.modelsvector3f;
6501         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6502         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6503         rsurface.tvector3f = rsurface.modeltvector3f;
6504         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6505         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6506         rsurface.normal3f  = rsurface.modelnormal3f;
6507         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6508         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6509         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6510 }
6511
6512 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)
6513 {
6514         rsurface.entity = r_refdef.scene.worldentity;
6515         rsurface.skeleton = NULL;
6516         rsurface.ent_skinnum = 0;
6517         rsurface.ent_qwskin = -1;
6518         rsurface.ent_shadertime = shadertime;
6519         rsurface.ent_flags = entflags;
6520         rsurface.modelnum_vertices = numvertices;
6521         rsurface.modelnum_triangles = numtriangles;
6522         if (rsurface.array_size < rsurface.modelnum_vertices)
6523                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6524         rsurface.matrix = *matrix;
6525         rsurface.inversematrix = *inversematrix;
6526         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6527         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6528         R_Mesh_Matrix(&rsurface.matrix);
6529         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6530         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6531         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6532         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6533         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6534         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6535         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6536         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6537         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6538         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6539         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6540         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
6541         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);
6542         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6543         rsurface.frameblend[0].lerp = 1;
6544         rsurface.ent_alttextures = false;
6545         rsurface.basepolygonfactor = r_refdef.polygonfactor;
6546         rsurface.basepolygonoffset = r_refdef.polygonoffset;
6547         if (wanttangents)
6548         {
6549                 rsurface.modelvertex3f = vertex3f;
6550                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6551                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6552                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6553         }
6554         else if (wantnormals)
6555         {
6556                 rsurface.modelvertex3f = vertex3f;
6557                 rsurface.modelsvector3f = NULL;
6558                 rsurface.modeltvector3f = NULL;
6559                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6560         }
6561         else
6562         {
6563                 rsurface.modelvertex3f = vertex3f;
6564                 rsurface.modelsvector3f = NULL;
6565                 rsurface.modeltvector3f = NULL;
6566                 rsurface.modelnormal3f = NULL;
6567         }
6568         rsurface.modelvertex3f_bufferobject = 0;
6569         rsurface.modelvertex3f_bufferoffset = 0;
6570         rsurface.modelsvector3f_bufferobject = 0;
6571         rsurface.modelsvector3f_bufferoffset = 0;
6572         rsurface.modeltvector3f_bufferobject = 0;
6573         rsurface.modeltvector3f_bufferoffset = 0;
6574         rsurface.modelnormal3f_bufferobject = 0;
6575         rsurface.modelnormal3f_bufferoffset = 0;
6576         rsurface.generatedvertex = true;
6577         rsurface.modellightmapcolor4f  = color4f;
6578         rsurface.modellightmapcolor4f_bufferobject = 0;
6579         rsurface.modellightmapcolor4f_bufferoffset = 0;
6580         rsurface.modeltexcoordtexture2f  = texcoord2f;
6581         rsurface.modeltexcoordtexture2f_bufferobject = 0;
6582         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6583         rsurface.modeltexcoordlightmap2f  = NULL;
6584         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6585         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6586         rsurface.modelelement3i = element3i;
6587         rsurface.modelelement3s = element3s;
6588         rsurface.modelelement3i_bufferobject = 0;
6589         rsurface.modelelement3s_bufferobject = 0;
6590         rsurface.modellightmapoffsets = NULL;
6591         rsurface.modelsurfaces = NULL;
6592         rsurface.vertex3f  = rsurface.modelvertex3f;
6593         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6594         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6595         rsurface.svector3f = rsurface.modelsvector3f;
6596         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6597         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6598         rsurface.tvector3f = rsurface.modeltvector3f;
6599         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6600         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6601         rsurface.normal3f  = rsurface.modelnormal3f;
6602         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6603         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6604         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6605
6606         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6607         {
6608                 if ((wantnormals || wanttangents) && !normal3f)
6609                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6610                 if (wanttangents && !svector3f)
6611                         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);
6612         }
6613 }
6614
6615 float RSurf_FogPoint(const float *v)
6616 {
6617         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6618         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6619         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6620         float FogHeightFade = r_refdef.fogheightfade;
6621         float fogfrac;
6622         unsigned int fogmasktableindex;
6623         if (r_refdef.fogplaneviewabove)
6624                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6625         else
6626                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6627         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6628         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6629 }
6630
6631 float RSurf_FogVertex(const float *v)
6632 {
6633         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6634         float FogPlaneViewDist = rsurface.fogplaneviewdist;
6635         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6636         float FogHeightFade = rsurface.fogheightfade;
6637         float fogfrac;
6638         unsigned int fogmasktableindex;
6639         if (r_refdef.fogplaneviewabove)
6640                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6641         else
6642                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6643         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6644         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6645 }
6646
6647 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6648 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6649 {
6650         int deformindex;
6651         int texturesurfaceindex;
6652         int i, j;
6653         float amplitude;
6654         float animpos;
6655         float scale;
6656         const float *v1, *in_tc;
6657         float *out_tc;
6658         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6659         float waveparms[4];
6660         q3shaderinfo_deform_t *deform;
6661         // 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
6662         if (rsurface.generatedvertex)
6663         {
6664                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6665                         generatenormals = true;
6666                 for (i = 0;i < Q3MAXDEFORMS;i++)
6667                 {
6668                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6669                         {
6670                                 generatetangents = true;
6671                                 generatenormals = true;
6672                         }
6673                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6674                                 generatenormals = true;
6675                 }
6676                 if (generatenormals && !rsurface.modelnormal3f)
6677                 {
6678                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6679                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6680                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6681                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6682                 }
6683                 if (generatetangents && !rsurface.modelsvector3f)
6684                 {
6685                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6686                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6687                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6688                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6689                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6690                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6691                         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);
6692                 }
6693         }
6694         rsurface.vertex3f  = rsurface.modelvertex3f;
6695         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6696         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6697         rsurface.svector3f = rsurface.modelsvector3f;
6698         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6699         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6700         rsurface.tvector3f = rsurface.modeltvector3f;
6701         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6702         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6703         rsurface.normal3f  = rsurface.modelnormal3f;
6704         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6705         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6706         // if vertices are deformed (sprite flares and things in maps, possibly
6707         // water waves, bulges and other deformations), generate them into
6708         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6709         // (may be static model data or generated data for an animated model, or
6710         //  the previous deform pass)
6711         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6712         {
6713                 switch (deform->deform)
6714                 {
6715                 default:
6716                 case Q3DEFORM_PROJECTIONSHADOW:
6717                 case Q3DEFORM_TEXT0:
6718                 case Q3DEFORM_TEXT1:
6719                 case Q3DEFORM_TEXT2:
6720                 case Q3DEFORM_TEXT3:
6721                 case Q3DEFORM_TEXT4:
6722                 case Q3DEFORM_TEXT5:
6723                 case Q3DEFORM_TEXT6:
6724                 case Q3DEFORM_TEXT7:
6725                 case Q3DEFORM_NONE:
6726                         break;
6727                 case Q3DEFORM_AUTOSPRITE:
6728                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6729                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6730                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6731                         VectorNormalize(newforward);
6732                         VectorNormalize(newright);
6733                         VectorNormalize(newup);
6734                         // make deformed versions of only the model vertices used by the specified surfaces
6735                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6736                         {
6737                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6738                                 // a single autosprite surface can contain multiple sprites...
6739                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
6740                                 {
6741                                         VectorClear(center);
6742                                         for (i = 0;i < 4;i++)
6743                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6744                                         VectorScale(center, 0.25f, center);
6745                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
6746                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6747                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6748                                         for (i = 0;i < 4;i++)
6749                                         {
6750                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6751                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6752                                         }
6753                                 }
6754                                 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);
6755                                 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);
6756                         }
6757                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6758                         rsurface.vertex3f_bufferobject = 0;
6759                         rsurface.vertex3f_bufferoffset = 0;
6760                         rsurface.svector3f = rsurface.array_deformedsvector3f;
6761                         rsurface.svector3f_bufferobject = 0;
6762                         rsurface.svector3f_bufferoffset = 0;
6763                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
6764                         rsurface.tvector3f_bufferobject = 0;
6765                         rsurface.tvector3f_bufferoffset = 0;
6766                         rsurface.normal3f = rsurface.array_deformednormal3f;
6767                         rsurface.normal3f_bufferobject = 0;
6768                         rsurface.normal3f_bufferoffset = 0;
6769                         break;
6770                 case Q3DEFORM_AUTOSPRITE2:
6771                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6772                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6773                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6774                         VectorNormalize(newforward);
6775                         VectorNormalize(newright);
6776                         VectorNormalize(newup);
6777                         // make deformed versions of only the model vertices used by the specified surfaces
6778                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6779                         {
6780                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6781                                 const float *v1, *v2;
6782                                 vec3_t start, end;
6783                                 float f, l;
6784                                 struct
6785                                 {
6786                                         float length2;
6787                                         const float *v1;
6788                                         const float *v2;
6789                                 }
6790                                 shortest[2];
6791                                 memset(shortest, 0, sizeof(shortest));
6792                                 // a single autosprite surface can contain multiple sprites...
6793                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
6794                                 {
6795                                         VectorClear(center);
6796                                         for (i = 0;i < 4;i++)
6797                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6798                                         VectorScale(center, 0.25f, center);
6799                                         // find the two shortest edges, then use them to define the
6800                                         // axis vectors for rotating around the central axis
6801                                         for (i = 0;i < 6;i++)
6802                                         {
6803                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6804                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6805 #if 0
6806                                                 Debug_PolygonBegin(NULL, 0);
6807                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6808                                                 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);
6809                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6810                                                 Debug_PolygonEnd();
6811 #endif
6812                                                 l = VectorDistance2(v1, v2);
6813                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6814                                                 if (v1[2] != v2[2])
6815                                                         l += (1.0f / 1024.0f);
6816                                                 if (shortest[0].length2 > l || i == 0)
6817                                                 {
6818                                                         shortest[1] = shortest[0];
6819                                                         shortest[0].length2 = l;
6820                                                         shortest[0].v1 = v1;
6821                                                         shortest[0].v2 = v2;
6822                                                 }
6823                                                 else if (shortest[1].length2 > l || i == 1)
6824                                                 {
6825                                                         shortest[1].length2 = l;
6826                                                         shortest[1].v1 = v1;
6827                                                         shortest[1].v2 = v2;
6828                                                 }
6829                                         }
6830                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6831                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6832 #if 0
6833                                         Debug_PolygonBegin(NULL, 0);
6834                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6835                                         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);
6836                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6837                                         Debug_PolygonEnd();
6838 #endif
6839                                         // this calculates the right vector from the shortest edge
6840                                         // and the up vector from the edge midpoints
6841                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6842                                         VectorNormalize(right);
6843                                         VectorSubtract(end, start, up);
6844                                         VectorNormalize(up);
6845                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6846                                         VectorSubtract(rsurface.localvieworigin, center, forward);
6847                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6848                                         VectorNegate(forward, forward);
6849                                         VectorReflect(forward, 0, up, forward);
6850                                         VectorNormalize(forward);
6851                                         CrossProduct(up, forward, newright);
6852                                         VectorNormalize(newright);
6853 #if 0
6854                                         Debug_PolygonBegin(NULL, 0);
6855                                         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);
6856                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6857                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
6858                                         Debug_PolygonEnd();
6859 #endif
6860 #if 0
6861                                         Debug_PolygonBegin(NULL, 0);
6862                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6863                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6864                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
6865                                         Debug_PolygonEnd();
6866 #endif
6867                                         // rotate the quad around the up axis vector, this is made
6868                                         // especially easy by the fact we know the quad is flat,
6869                                         // so we only have to subtract the center position and
6870                                         // measure distance along the right vector, and then
6871                                         // multiply that by the newright vector and add back the
6872                                         // center position
6873                                         // we also need to subtract the old position to undo the
6874                                         // displacement from the center, which we do with a
6875                                         // DotProduct, the subtraction/addition of center is also
6876                                         // optimized into DotProducts here
6877                                         l = DotProduct(right, center);
6878                                         for (i = 0;i < 4;i++)
6879                                         {
6880                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6881                                                 f = DotProduct(right, v1) - l;
6882                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6883                                         }
6884                                 }
6885                                 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);
6886                                 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);
6887                         }
6888                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6889                         rsurface.vertex3f_bufferobject = 0;
6890                         rsurface.vertex3f_bufferoffset = 0;
6891                         rsurface.svector3f = rsurface.array_deformedsvector3f;
6892                         rsurface.svector3f_bufferobject = 0;
6893                         rsurface.svector3f_bufferoffset = 0;
6894                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
6895                         rsurface.tvector3f_bufferobject = 0;
6896                         rsurface.tvector3f_bufferoffset = 0;
6897                         rsurface.normal3f = rsurface.array_deformednormal3f;
6898                         rsurface.normal3f_bufferobject = 0;
6899                         rsurface.normal3f_bufferoffset = 0;
6900                         break;
6901                 case Q3DEFORM_NORMAL:
6902                         // deform the normals to make reflections wavey
6903                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6904                         {
6905                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6906                                 for (j = 0;j < surface->num_vertices;j++)
6907                                 {
6908                                         float vertex[3];
6909                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
6910                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6911                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
6912                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6913                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6914                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6915                                         VectorNormalize(normal);
6916                                 }
6917                                 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);
6918                         }
6919                         rsurface.svector3f = rsurface.array_deformedsvector3f;
6920                         rsurface.svector3f_bufferobject = 0;
6921                         rsurface.svector3f_bufferoffset = 0;
6922                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
6923                         rsurface.tvector3f_bufferobject = 0;
6924                         rsurface.tvector3f_bufferoffset = 0;
6925                         rsurface.normal3f = rsurface.array_deformednormal3f;
6926                         rsurface.normal3f_bufferobject = 0;
6927                         rsurface.normal3f_bufferoffset = 0;
6928                         break;
6929                 case Q3DEFORM_WAVE:
6930                         // deform vertex array to make wavey water and flags and such
6931                         waveparms[0] = deform->waveparms[0];
6932                         waveparms[1] = deform->waveparms[1];
6933                         waveparms[2] = deform->waveparms[2];
6934                         waveparms[3] = deform->waveparms[3];
6935                         // this is how a divisor of vertex influence on deformation
6936                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6937                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6938                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6939                         {
6940                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6941                                 for (j = 0;j < surface->num_vertices;j++)
6942                                 {
6943                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
6944                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
6945                                         // if the wavefunc depends on time, evaluate it per-vertex
6946                                         if (waveparms[3])
6947                                         {
6948                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6949                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6950                                         }
6951                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
6952                                 }
6953                         }
6954                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6955                         rsurface.vertex3f_bufferobject = 0;
6956                         rsurface.vertex3f_bufferoffset = 0;
6957                         break;
6958                 case Q3DEFORM_BULGE:
6959                         // deform vertex array to make the surface have moving bulges
6960                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6961                         {
6962                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6963                                 for (j = 0;j < surface->num_vertices;j++)
6964                                 {
6965                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6966                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6967                                 }
6968                         }
6969                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6970                         rsurface.vertex3f_bufferobject = 0;
6971                         rsurface.vertex3f_bufferoffset = 0;
6972                         break;
6973                 case Q3DEFORM_MOVE:
6974                         // deform vertex array
6975                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6976                         VectorScale(deform->parms, scale, waveparms);
6977                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6978                         {
6979                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6980                                 for (j = 0;j < surface->num_vertices;j++)
6981                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6982                         }
6983                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6984                         rsurface.vertex3f_bufferobject = 0;
6985                         rsurface.vertex3f_bufferoffset = 0;
6986                         break;
6987                 }
6988         }
6989         // generate texcoords based on the chosen texcoord source
6990         switch(rsurface.texture->tcgen.tcgen)
6991         {
6992         default:
6993         case Q3TCGEN_TEXTURE:
6994                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
6995                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
6996                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
6997                 break;
6998         case Q3TCGEN_LIGHTMAP:
6999                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
7000                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
7001                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
7002                 break;
7003         case Q3TCGEN_VECTOR:
7004                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7005                 {
7006                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7007                         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)
7008                         {
7009                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
7010                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
7011                         }
7012                 }
7013                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7014                 rsurface.texcoordtexture2f_bufferobject  = 0;
7015                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7016                 break;
7017         case Q3TCGEN_ENVIRONMENT:
7018                 // make environment reflections using a spheremap
7019                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7020                 {
7021                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7022                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
7023                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
7024                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
7025                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
7026                         {
7027                                 // identical to Q3A's method, but executed in worldspace so
7028                                 // carried models can be shiny too
7029
7030                                 float viewer[3], d, reflected[3], worldreflected[3];
7031
7032                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
7033                                 // VectorNormalize(viewer);
7034
7035                                 d = DotProduct(normal, viewer);
7036
7037                                 reflected[0] = normal[0]*2*d - viewer[0];
7038                                 reflected[1] = normal[1]*2*d - viewer[1];
7039                                 reflected[2] = normal[2]*2*d - viewer[2];
7040                                 // note: this is proportinal to viewer, so we can normalize later
7041
7042                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7043                                 VectorNormalize(worldreflected);
7044
7045                                 // note: this sphere map only uses world x and z!
7046                                 // so positive and negative y will LOOK THE SAME.
7047                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7048                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7049                         }
7050                 }
7051                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7052                 rsurface.texcoordtexture2f_bufferobject  = 0;
7053                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7054                 break;
7055         }
7056         // the only tcmod that needs software vertex processing is turbulent, so
7057         // check for it here and apply the changes if needed
7058         // and we only support that as the first one
7059         // (handling a mixture of turbulent and other tcmods would be problematic
7060         //  without punting it entirely to a software path)
7061         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7062         {
7063                 amplitude = rsurface.texture->tcmods[0].parms[1];
7064                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7065                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7066                 {
7067                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7068                         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)
7069                         {
7070                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7071                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7072                         }
7073                 }
7074                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
7075                 rsurface.texcoordtexture2f_bufferobject  = 0;
7076                 rsurface.texcoordtexture2f_bufferoffset  = 0;
7077         }
7078         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
7079         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7080         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7081         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7082 }
7083
7084 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7085 {
7086         int i, j;
7087         const msurface_t *surface = texturesurfacelist[0];
7088         const msurface_t *surface2;
7089         int firstvertex;
7090         int endvertex;
7091         int numvertices;
7092         int numtriangles;
7093         // TODO: lock all array ranges before render, rather than on each surface
7094         if (texturenumsurfaces == 1)
7095         {
7096                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7097                 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);
7098         }
7099         else if (r_batchmode.integer == 2)
7100         {
7101                 #define MAXBATCHTRIANGLES 4096
7102                 int batchtriangles = 0;
7103                 static int batchelements[MAXBATCHTRIANGLES*3];
7104                 for (i = 0;i < texturenumsurfaces;i = j)
7105                 {
7106                         surface = texturesurfacelist[i];
7107                         j = i + 1;
7108                         if (surface->num_triangles > MAXBATCHTRIANGLES)
7109                         {
7110                                 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);
7111                                 continue;
7112                         }
7113                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7114                         batchtriangles = surface->num_triangles;
7115                         firstvertex = surface->num_firstvertex;
7116                         endvertex = surface->num_firstvertex + surface->num_vertices;
7117                         for (;j < texturenumsurfaces;j++)
7118                         {
7119                                 surface2 = texturesurfacelist[j];
7120                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7121                                         break;
7122                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7123                                 batchtriangles += surface2->num_triangles;
7124                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
7125                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7126                         }
7127                         surface2 = texturesurfacelist[j-1];
7128                         numvertices = endvertex - firstvertex;
7129                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7130                 }
7131         }
7132         else if (r_batchmode.integer == 1)
7133         {
7134                 for (i = 0;i < texturenumsurfaces;i = j)
7135                 {
7136                         surface = texturesurfacelist[i];
7137                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7138                                 if (texturesurfacelist[j] != surface2)
7139                                         break;
7140                         surface2 = texturesurfacelist[j-1];
7141                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7142                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7143                         GL_LockArrays(surface->num_firstvertex, numvertices);
7144                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7145                 }
7146         }
7147         else
7148         {
7149                 for (i = 0;i < texturenumsurfaces;i++)
7150                 {
7151                         surface = texturesurfacelist[i];
7152                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7153                         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);
7154                 }
7155         }
7156 }
7157
7158 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
7159 {
7160         int i, planeindex, vertexindex;
7161         float d, bestd;
7162         vec3_t vert;
7163         const float *v;
7164         r_waterstate_waterplane_t *p, *bestp;
7165         const msurface_t *surface;
7166         if (r_waterstate.renderingscene)
7167                 return;
7168         for (i = 0;i < texturenumsurfaces;i++)
7169         {
7170                 surface = texturesurfacelist[i];
7171                 if (lightmaptexunit >= 0)
7172                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7173                 if (deluxemaptexunit >= 0)
7174                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7175                 // pick the closest matching water plane
7176                 bestd = 0;
7177                 bestp = NULL;
7178                 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7179                 {
7180                         d = 0;
7181                         for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7182                         {
7183                                 Matrix4x4_Transform(&rsurface.matrix, v, vert);
7184                                 d += fabs(PlaneDiff(vert, &p->plane));
7185                         }
7186                         if (bestd > d || !bestp)
7187                         {
7188                                 bestd = d;
7189                                 bestp = p;
7190                         }
7191                 }
7192                 if (bestp)
7193                 {
7194                         if (refractiontexunit >= 0)
7195                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
7196                         if (reflectiontexunit >= 0)
7197                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
7198                 }
7199                 else
7200                 {
7201                         if (refractiontexunit >= 0)
7202                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
7203                         if (reflectiontexunit >= 0)
7204                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
7205                 }
7206                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7207                 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);
7208         }
7209 }
7210
7211 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
7212 {
7213         int i;
7214         int j;
7215         const msurface_t *surface = texturesurfacelist[0];
7216         const msurface_t *surface2;
7217         int firstvertex;
7218         int endvertex;
7219         int numvertices;
7220         int numtriangles;
7221         // TODO: lock all array ranges before render, rather than on each surface
7222         if (texturenumsurfaces == 1)
7223         {
7224                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7225                 if (deluxemaptexunit >= 0)
7226                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7227                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7228                 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);
7229         }
7230         else if (r_batchmode.integer == 2)
7231         {
7232                 #define MAXBATCHTRIANGLES 4096
7233                 int batchtriangles = 0;
7234                 int batchelements[MAXBATCHTRIANGLES*3];
7235                 for (i = 0;i < texturenumsurfaces;i = j)
7236                 {
7237                         surface = texturesurfacelist[i];
7238                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7239                         if (deluxemaptexunit >= 0)
7240                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7241                         j = i + 1;
7242                         if (surface->num_triangles > MAXBATCHTRIANGLES)
7243                         {
7244                                 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);
7245                                 continue;
7246                         }
7247                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7248                         batchtriangles = surface->num_triangles;
7249                         firstvertex = surface->num_firstvertex;
7250                         endvertex = surface->num_firstvertex + surface->num_vertices;
7251                         for (;j < texturenumsurfaces;j++)
7252                         {
7253                                 surface2 = texturesurfacelist[j];
7254                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7255                                         break;
7256                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7257                                 batchtriangles += surface2->num_triangles;
7258                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
7259                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7260                         }
7261                         surface2 = texturesurfacelist[j-1];
7262                         numvertices = endvertex - firstvertex;
7263                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7264                 }
7265         }
7266         else if (r_batchmode.integer == 1)
7267         {
7268 #if 0
7269                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
7270                 for (i = 0;i < texturenumsurfaces;i = j)
7271                 {
7272                         surface = texturesurfacelist[i];
7273                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7274                                 if (texturesurfacelist[j] != surface2)
7275                                         break;
7276                         Con_Printf(" %i", j - i);
7277                 }
7278                 Con_Printf("\n");
7279                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
7280 #endif
7281                 for (i = 0;i < texturenumsurfaces;i = j)
7282                 {
7283                         surface = texturesurfacelist[i];
7284                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7285                         if (deluxemaptexunit >= 0)
7286                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7287                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7288                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7289                                         break;
7290 #if 0
7291                         Con_Printf(" %i", j - i);
7292 #endif
7293                         surface2 = texturesurfacelist[j-1];
7294                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7295                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7296                         GL_LockArrays(surface->num_firstvertex, numvertices);
7297                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7298                 }
7299 #if 0
7300                 Con_Printf("\n");
7301 #endif
7302         }
7303         else
7304         {
7305                 for (i = 0;i < texturenumsurfaces;i++)
7306                 {
7307                         surface = texturesurfacelist[i];
7308                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7309                         if (deluxemaptexunit >= 0)
7310                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7311                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7312                         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);
7313                 }
7314         }
7315 }
7316
7317 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7318 {
7319         int j;
7320         int texturesurfaceindex;
7321         if (r_showsurfaces.integer == 2)
7322         {
7323                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7324                 {
7325                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7326                         for (j = 0;j < surface->num_triangles;j++)
7327                         {
7328                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7329                                 GL_Color(f, f, f, 1);
7330                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7331                         }
7332                 }
7333         }
7334         else
7335         {
7336                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7337                 {
7338                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7339                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
7340                         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);
7341                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7342                         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);
7343                 }
7344         }
7345 }
7346
7347 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7348 {
7349         int texturesurfaceindex;
7350         int i;
7351         const float *v;
7352         float *c2;
7353         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7354         {
7355                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7356                 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)
7357                 {
7358                         c2[0] = 0.5;
7359                         c2[1] = 0.5;
7360                         c2[2] = 0.5;
7361                         c2[3] = 1;
7362                 }
7363         }
7364         rsurface.lightmapcolor4f = rsurface.array_color4f;
7365         rsurface.lightmapcolor4f_bufferobject = 0;
7366         rsurface.lightmapcolor4f_bufferoffset = 0;
7367 }
7368
7369 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7370 {
7371         int texturesurfaceindex;
7372         int i;
7373         float f;
7374         const float *v;
7375         const float *c;
7376         float *c2;
7377         if (rsurface.lightmapcolor4f)
7378         {
7379                 // generate color arrays for the surfaces in this list
7380                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7381                 {
7382                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7383                         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)
7384                         {
7385                                 f = RSurf_FogVertex(v);
7386                                 c2[0] = c[0] * f;
7387                                 c2[1] = c[1] * f;
7388                                 c2[2] = c[2] * f;
7389                                 c2[3] = c[3];
7390                         }
7391                 }
7392         }
7393         else
7394         {
7395                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7396                 {
7397                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7398                         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)
7399                         {
7400                                 f = RSurf_FogVertex(v);
7401                                 c2[0] = f;
7402                                 c2[1] = f;
7403                                 c2[2] = f;
7404                                 c2[3] = 1;
7405                         }
7406                 }
7407         }
7408         rsurface.lightmapcolor4f = rsurface.array_color4f;
7409         rsurface.lightmapcolor4f_bufferobject = 0;
7410         rsurface.lightmapcolor4f_bufferoffset = 0;
7411 }
7412
7413 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7414 {
7415         int texturesurfaceindex;
7416         int i;
7417         float f;
7418         const float *v;
7419         const float *c;
7420         float *c2;
7421         if (!rsurface.lightmapcolor4f)
7422                 return;
7423         // generate color arrays for the surfaces in this list
7424         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7425         {
7426                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7427                 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)
7428                 {
7429                         f = RSurf_FogVertex(v);
7430                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7431                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7432                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7433                         c2[3] = c[3];
7434                 }
7435         }
7436         rsurface.lightmapcolor4f = rsurface.array_color4f;
7437         rsurface.lightmapcolor4f_bufferobject = 0;
7438         rsurface.lightmapcolor4f_bufferoffset = 0;
7439 }
7440
7441 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7442 {
7443         int texturesurfaceindex;
7444         int i;
7445         const float *c;
7446         float *c2;
7447         if (!rsurface.lightmapcolor4f)
7448                 return;
7449         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7450         {
7451                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7452                 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)
7453                 {
7454                         c2[0] = c[0] * r;
7455                         c2[1] = c[1] * g;
7456                         c2[2] = c[2] * b;
7457                         c2[3] = c[3] * a;
7458                 }
7459         }
7460         rsurface.lightmapcolor4f = rsurface.array_color4f;
7461         rsurface.lightmapcolor4f_bufferobject = 0;
7462         rsurface.lightmapcolor4f_bufferoffset = 0;
7463 }
7464
7465 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7466 {
7467         int texturesurfaceindex;
7468         int i;
7469         const float *c;
7470         float *c2;
7471         if (!rsurface.lightmapcolor4f)
7472                 return;
7473         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7474         {
7475                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7476                 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)
7477                 {
7478                         c2[0] = c[0] + r_refdef.scene.ambient;
7479                         c2[1] = c[1] + r_refdef.scene.ambient;
7480                         c2[2] = c[2] + r_refdef.scene.ambient;
7481                         c2[3] = c[3];
7482                 }
7483         }
7484         rsurface.lightmapcolor4f = rsurface.array_color4f;
7485         rsurface.lightmapcolor4f_bufferobject = 0;
7486         rsurface.lightmapcolor4f_bufferoffset = 0;
7487 }
7488
7489 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7490 {
7491         // TODO: optimize
7492         rsurface.lightmapcolor4f = NULL;
7493         rsurface.lightmapcolor4f_bufferobject = 0;
7494         rsurface.lightmapcolor4f_bufferoffset = 0;
7495         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7496         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7497         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7498         GL_Color(r, g, b, a);
7499         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7500 }
7501
7502 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7503 {
7504         // TODO: optimize applyfog && applycolor case
7505         // just apply fog if necessary, and tint the fog color array if necessary
7506         rsurface.lightmapcolor4f = NULL;
7507         rsurface.lightmapcolor4f_bufferobject = 0;
7508         rsurface.lightmapcolor4f_bufferoffset = 0;
7509         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7510         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7511         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7512         GL_Color(r, g, b, a);
7513         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7514 }
7515
7516 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7517 {
7518         int texturesurfaceindex;
7519         int i;
7520         float *c;
7521         // TODO: optimize
7522         if (texturesurfacelist[0]->lightmapinfo)
7523         {
7524                 // generate color arrays for the surfaces in this list
7525                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7526                 {
7527                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7528                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7529                         {
7530                                 if (surface->lightmapinfo->samples)
7531                                 {
7532                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7533                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7534                                         VectorScale(lm, scale, c);
7535                                         if (surface->lightmapinfo->styles[1] != 255)
7536                                         {
7537                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7538                                                 lm += size3;
7539                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7540                                                 VectorMA(c, scale, lm, c);
7541                                                 if (surface->lightmapinfo->styles[2] != 255)
7542                                                 {
7543                                                         lm += size3;
7544                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7545                                                         VectorMA(c, scale, lm, c);
7546                                                         if (surface->lightmapinfo->styles[3] != 255)
7547                                                         {
7548                                                                 lm += size3;
7549                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7550                                                                 VectorMA(c, scale, lm, c);
7551                                                         }
7552                                                 }
7553                                         }
7554                                 }
7555                                 else
7556                                         VectorClear(c);
7557                                 c[3] = 1;
7558                         }
7559                 }
7560                 rsurface.lightmapcolor4f = rsurface.array_color4f;
7561                 rsurface.lightmapcolor4f_bufferobject = 0;
7562                 rsurface.lightmapcolor4f_bufferoffset = 0;
7563         }
7564         else
7565         {
7566                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7567                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7568                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7569         }
7570         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7571         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7572         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7573         GL_Color(r, g, b, a);
7574         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7575 }
7576
7577 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7578 {
7579         int texturesurfaceindex;
7580         int i;
7581         float f;
7582         float alpha;
7583         const float *v;
7584         const float *n;
7585         float *c;
7586         vec3_t ambientcolor;
7587         vec3_t diffusecolor;
7588         vec3_t lightdir;
7589         // TODO: optimize
7590         // model lighting
7591         VectorCopy(rsurface.modellight_lightdir, lightdir);
7592         f = 0.5f * r_refdef.lightmapintensity;
7593         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7594         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7595         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7596         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7597         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7598         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7599         alpha = *a;
7600         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7601         {
7602                 // generate color arrays for the surfaces in this list
7603                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7604                 {
7605                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7606                         int numverts = surface->num_vertices;
7607                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7608                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
7609                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7610                         // q3-style directional shading
7611                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7612                         {
7613                                 if ((f = DotProduct(n, lightdir)) > 0)
7614                                         VectorMA(ambientcolor, f, diffusecolor, c);
7615                                 else
7616                                         VectorCopy(ambientcolor, c);
7617                                 c[3] = alpha;
7618                         }
7619                 }
7620                 *r = 1;
7621                 *g = 1;
7622                 *b = 1;
7623                 *a = 1;
7624                 rsurface.lightmapcolor4f = rsurface.array_color4f;
7625                 rsurface.lightmapcolor4f_bufferobject = 0;
7626                 rsurface.lightmapcolor4f_bufferoffset = 0;
7627                 *applycolor = false;
7628         }
7629         else
7630         {
7631                 *r = ambientcolor[0];
7632                 *g = ambientcolor[1];
7633                 *b = ambientcolor[2];
7634                 rsurface.lightmapcolor4f = NULL;
7635                 rsurface.lightmapcolor4f_bufferobject = 0;
7636                 rsurface.lightmapcolor4f_bufferoffset = 0;
7637         }
7638 }
7639
7640 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7641 {
7642         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7643         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7644         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7645         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7646         GL_Color(r, g, b, a);
7647         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7648 }
7649
7650 void RSurf_SetupDepthAndCulling(void)
7651 {
7652         // submodels are biased to avoid z-fighting with world surfaces that they
7653         // may be exactly overlapping (avoids z-fighting artifacts on certain
7654         // doors and things in Quake maps)
7655         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7656         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7657         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7658         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7659 }
7660
7661 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7662 {
7663         // transparent sky would be ridiculous
7664         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7665                 return;
7666         R_SetupGenericShader(false);
7667         skyrenderlater = true;
7668         RSurf_SetupDepthAndCulling();
7669         GL_DepthMask(true);
7670         // LordHavoc: HalfLife maps have freaky skypolys so don't use
7671         // skymasking on them, and Quake3 never did sky masking (unlike
7672         // software Quake and software Quake2), so disable the sky masking
7673         // in Quake3 maps as it causes problems with q3map2 sky tricks,
7674         // and skymasking also looks very bad when noclipping outside the
7675         // level, so don't use it then either.
7676         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7677         {
7678                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7679                 R_Mesh_ColorPointer(NULL, 0, 0);
7680                 R_Mesh_ResetTextureState();
7681                 if (skyrendermasked)
7682                 {
7683                         R_SetupDepthOrShadowShader();
7684                         // depth-only (masking)
7685                         GL_ColorMask(0,0,0,0);
7686                         // just to make sure that braindead drivers don't draw
7687                         // anything despite that colormask...
7688                         GL_BlendFunc(GL_ZERO, GL_ONE);
7689                 }
7690                 else
7691                 {
7692                         R_SetupGenericShader(false);
7693                         // fog sky
7694                         GL_BlendFunc(GL_ONE, GL_ZERO);
7695                 }
7696                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7697                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7698                 if (skyrendermasked)
7699                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7700         }
7701         R_Mesh_ResetTextureState();
7702         GL_Color(1, 1, 1, 1);
7703 }
7704
7705 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
7706 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
7707 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
7708 {
7709         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7710                 return;
7711
7712         R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7713         R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7714         R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7715         R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7716         if (rsurface.texture->backgroundcurrentskinframe)
7717         {
7718                 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7719                 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7720                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7721                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7722         }
7723         if (rsurface.texture->colormapping)
7724         {
7725                 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7726                 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7727         }
7728         R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7729         if (r_shadow_usingdeferredprepass)
7730         {
7731                 R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture));
7732                 R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture));
7733         }
7734         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7735                 R_Mesh_ColorPointer(NULL, 0, 0);
7736         else
7737                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7738
7739         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass)
7740         {
7741                 // render background
7742                 GL_BlendFunc(GL_ONE, GL_ZERO);
7743                 GL_DepthMask(true);
7744                 GL_AlphaTest(false);
7745
7746                 GL_Color(1, 1, 1, 1);
7747                 R_Mesh_ColorPointer(NULL, 0, 0);
7748
7749                 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7750                 if (r_glsl_permutation)
7751                 {
7752                         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7753                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7754                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7755                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7756                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7757                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7758                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
7759                 }
7760                 GL_LockArrays(0, 0);
7761
7762                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7763                 GL_DepthMask(false);
7764                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7765                         R_Mesh_ColorPointer(NULL, 0, 0);
7766                 else
7767                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7768                 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7769                 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7770         }
7771
7772         R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
7773         if (!r_glsl_permutation)
7774                 return;
7775
7776         RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7777         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7778         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7779         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7780         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7781         if (!prepass)
7782                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7783
7784         if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7785         {
7786                 GL_BlendFunc(GL_ONE, GL_ZERO);
7787                 GL_DepthMask(true);
7788                 GL_AlphaTest(false);
7789         }
7790         else
7791         {
7792                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7793                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7794                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
7795         }
7796
7797         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7798         {
7799                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7800                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
7801                 else
7802                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7803         }
7804         else
7805         {
7806                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7807                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
7808                 else
7809                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7810         }
7811         GL_LockArrays(0, 0);
7812 }
7813
7814 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7815 {
7816         // OpenGL 1.3 path - anything not completely ancient
7817         int texturesurfaceindex;
7818         qboolean applycolor;
7819         qboolean applyfog;
7820         int layerindex;
7821         const texturelayer_t *layer;
7822         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7823
7824         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7825         {
7826                 vec4_t layercolor;
7827                 int layertexrgbscale;
7828                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7829                 {
7830                         if (layerindex == 0)
7831                                 GL_AlphaTest(true);
7832                         else
7833                         {
7834                                 GL_AlphaTest(false);
7835                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7836                         }
7837                 }
7838                 GL_DepthMask(layer->depthmask && writedepth);
7839                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7840                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7841                 {
7842                         layertexrgbscale = 4;
7843                         VectorScale(layer->color, 0.25f, layercolor);
7844                 }
7845                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7846                 {
7847                         layertexrgbscale = 2;
7848                         VectorScale(layer->color, 0.5f, layercolor);
7849                 }
7850                 else
7851                 {
7852                         layertexrgbscale = 1;
7853                         VectorScale(layer->color, 1.0f, layercolor);
7854                 }
7855                 layercolor[3] = layer->color[3];
7856                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7857                 R_Mesh_ColorPointer(NULL, 0, 0);
7858                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
7859                 switch (layer->type)
7860                 {
7861                 case TEXTURELAYERTYPE_LITTEXTURE:
7862                         // single-pass lightmapped texture with 2x rgbscale
7863                         R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
7864                         R_Mesh_TexMatrix(0, NULL);
7865                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7866                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7867                         R_Mesh_TexBind(1, R_GetTexture(layer->texture));
7868                         R_Mesh_TexMatrix(1, &layer->texmatrix);
7869                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7870                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7871                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7872                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7873                         else if (rsurface.uselightmaptexture)
7874                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7875                         else
7876                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7877                         break;
7878                 case TEXTURELAYERTYPE_TEXTURE:
7879                         // singletexture unlit texture with transparency support
7880                         R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7881                         R_Mesh_TexMatrix(0, &layer->texmatrix);
7882                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7883                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7884                         R_Mesh_TexBind(1, 0);
7885                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
7886                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7887                         break;
7888                 case TEXTURELAYERTYPE_FOG:
7889                         // singletexture fogging
7890                         if (layer->texture)
7891                         {
7892                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7893                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
7894                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7895                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7896                         }
7897                         else
7898                         {
7899                                 R_Mesh_TexBind(0, 0);
7900                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
7901                         }
7902                         R_Mesh_TexBind(1, 0);
7903                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
7904                         // generate a color array for the fog pass
7905                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7906                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7907                         {
7908                                 int i;
7909                                 float f;
7910                                 const float *v;
7911                                 float *c;
7912                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7913                                 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)
7914                                 {
7915                                         f = 1 - RSurf_FogVertex(v);
7916                                         c[0] = layercolor[0];
7917                                         c[1] = layercolor[1];
7918                                         c[2] = layercolor[2];
7919                                         c[3] = f * layercolor[3];
7920                                 }
7921                         }
7922                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7923                         break;
7924                 default:
7925                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7926                 }
7927                 GL_LockArrays(0, 0);
7928         }
7929         CHECKGLERROR
7930         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7931         {
7932                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7933                 GL_AlphaTest(false);
7934         }
7935 }
7936
7937 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7938 {
7939         // OpenGL 1.1 - crusty old voodoo path
7940         int texturesurfaceindex;
7941         qboolean applyfog;
7942         int layerindex;
7943         const texturelayer_t *layer;
7944         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7945
7946         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7947         {
7948                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7949                 {
7950                         if (layerindex == 0)
7951                                 GL_AlphaTest(true);
7952                         else
7953                         {
7954                                 GL_AlphaTest(false);
7955                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7956                         }
7957                 }
7958                 GL_DepthMask(layer->depthmask && writedepth);
7959                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7960                 R_Mesh_ColorPointer(NULL, 0, 0);
7961                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
7962                 switch (layer->type)
7963                 {
7964                 case TEXTURELAYERTYPE_LITTEXTURE:
7965                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7966                         {
7967                                 // two-pass lit texture with 2x rgbscale
7968                                 // first the lightmap pass
7969                                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
7970                                 R_Mesh_TexMatrix(0, NULL);
7971                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7972                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7973                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7974                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7975                                 else if (rsurface.uselightmaptexture)
7976                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7977                                 else
7978                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7979                                 GL_LockArrays(0, 0);
7980                                 // then apply the texture to it
7981                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7982                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7983                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
7984                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7985                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7986                                 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);
7987                         }
7988                         else
7989                         {
7990                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7991                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7992                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
7993                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7994                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7995                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7996                                         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);
7997                                 else
7998                                         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);
7999                         }
8000                         break;
8001                 case TEXTURELAYERTYPE_TEXTURE:
8002                         // singletexture unlit texture with transparency support
8003                         R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8004                         R_Mesh_TexMatrix(0, &layer->texmatrix);
8005                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8006                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8007                         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);
8008                         break;
8009                 case TEXTURELAYERTYPE_FOG:
8010                         // singletexture fogging
8011                         if (layer->texture)
8012                         {
8013                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8014                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
8015                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8016                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8017                         }
8018                         else
8019                         {
8020                                 R_Mesh_TexBind(0, 0);
8021                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8022                         }
8023                         // generate a color array for the fog pass
8024                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8025                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8026                         {
8027                                 int i;
8028                                 float f;
8029                                 const float *v;
8030                                 float *c;
8031                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8032                                 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)
8033                                 {
8034                                         f = 1 - RSurf_FogVertex(v);
8035                                         c[0] = layer->color[0];
8036                                         c[1] = layer->color[1];
8037                                         c[2] = layer->color[2];
8038                                         c[3] = f * layer->color[3];
8039                                 }
8040                         }
8041                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8042                         break;
8043                 default:
8044                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8045                 }
8046                 GL_LockArrays(0, 0);
8047         }
8048         CHECKGLERROR
8049         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8050         {
8051                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8052                 GL_AlphaTest(false);
8053         }
8054 }
8055
8056 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8057 {
8058         float c[4];
8059
8060         GL_AlphaTest(false);
8061         R_Mesh_ColorPointer(NULL, 0, 0);
8062         R_Mesh_ResetTextureState();
8063         R_SetupGenericShader(false);
8064
8065         if(rsurface.texture && rsurface.texture->currentskinframe)
8066         {
8067                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8068                 c[3] *= rsurface.texture->currentalpha;
8069         }
8070         else
8071         {
8072                 c[0] = 1;
8073                 c[1] = 0;
8074                 c[2] = 1;
8075                 c[3] = 1;
8076         }
8077
8078         if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
8079         {
8080                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8081                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8082                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8083         }
8084
8085         // brighten it up (as texture value 127 means "unlit")
8086         c[0] *= 2 * r_refdef.view.colorscale;
8087         c[1] *= 2 * r_refdef.view.colorscale;
8088         c[2] *= 2 * r_refdef.view.colorscale;
8089
8090         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8091                 c[3] *= r_wateralpha.value;
8092
8093         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8094         {
8095                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8096                 GL_DepthMask(false);
8097         }
8098         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8099         {
8100                 GL_BlendFunc(GL_ONE, GL_ONE);
8101                 GL_DepthMask(false);
8102         }
8103         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8104         {
8105                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8106                 GL_DepthMask(false);
8107         }
8108         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8109         {
8110                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8111                 GL_DepthMask(false);
8112         }
8113         else
8114         {
8115                 GL_BlendFunc(GL_ONE, GL_ZERO);
8116                 GL_DepthMask(writedepth);
8117         }
8118
8119         rsurface.lightmapcolor4f = NULL;
8120
8121         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8122         {
8123                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8124
8125                 rsurface.lightmapcolor4f = NULL;
8126                 rsurface.lightmapcolor4f_bufferobject = 0;
8127                 rsurface.lightmapcolor4f_bufferoffset = 0;
8128         }
8129         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8130         {
8131                 qboolean applycolor = true;
8132                 float one = 1.0;
8133
8134                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8135
8136                 r_refdef.lightmapintensity = 1;
8137                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8138                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8139         }
8140         else
8141         {
8142                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8143
8144                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8145                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8146                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8147         }
8148
8149         if(!rsurface.lightmapcolor4f)
8150                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8151
8152         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8153         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8154         if(r_refdef.fogenabled)
8155                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8156
8157         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8158         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8159 }
8160
8161 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8162 {
8163         CHECKGLERROR
8164         RSurf_SetupDepthAndCulling();
8165         if (r_showsurfaces.integer == 3 && !prepass)
8166         {
8167                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8168                 return;
8169         }
8170         switch (vid.renderpath)
8171         {
8172         case RENDERPATH_GL20:
8173                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8174                 break;
8175         case RENDERPATH_GL13:
8176                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8177                 break;
8178         case RENDERPATH_GL11:
8179                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8180                 break;
8181         }
8182         CHECKGLERROR
8183 }
8184
8185 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8186 {
8187         CHECKGLERROR
8188         RSurf_SetupDepthAndCulling();
8189         if (r_showsurfaces.integer == 3 && !prepass)
8190         {
8191                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8192                 return;
8193         }
8194         switch (vid.renderpath)
8195         {
8196         case RENDERPATH_GL20:
8197                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8198                 break;
8199         case RENDERPATH_GL13:
8200                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8201                 break;
8202         case RENDERPATH_GL11:
8203                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8204                 break;
8205         }
8206         CHECKGLERROR
8207 }
8208
8209 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8210 {
8211         int i, j;
8212         int texturenumsurfaces, endsurface;
8213         texture_t *texture;
8214         const msurface_t *surface;
8215         const msurface_t *texturesurfacelist[256];
8216
8217         // if the model is static it doesn't matter what value we give for
8218         // wantnormals and wanttangents, so this logic uses only rules applicable
8219         // to a model, knowing that they are meaningless otherwise
8220         if (ent == r_refdef.scene.worldentity)
8221                 RSurf_ActiveWorldEntity();
8222         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8223                 RSurf_ActiveModelEntity(ent, false, false, false);
8224         else
8225         {
8226                 switch (vid.renderpath)
8227                 {
8228                 case RENDERPATH_GL20:
8229                         RSurf_ActiveModelEntity(ent, true, true, false);
8230                         break;
8231                 case RENDERPATH_GL13:
8232                 case RENDERPATH_GL11:
8233                         RSurf_ActiveModelEntity(ent, true, false, false);
8234                         break;
8235                 }
8236         }
8237
8238         if (r_transparentdepthmasking.integer)
8239         {
8240                 qboolean setup = false;
8241                 for (i = 0;i < numsurfaces;i = j)
8242                 {
8243                         j = i + 1;
8244                         surface = rsurface.modelsurfaces + surfacelist[i];
8245                         texture = surface->texture;
8246                         rsurface.texture = R_GetCurrentTexture(texture);
8247                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8248                         // scan ahead until we find a different texture
8249                         endsurface = min(i + 1024, numsurfaces);
8250                         texturenumsurfaces = 0;
8251                         texturesurfacelist[texturenumsurfaces++] = surface;
8252                         for (;j < endsurface;j++)
8253                         {
8254                                 surface = rsurface.modelsurfaces + surfacelist[j];
8255                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8256                                         break;
8257                                 texturesurfacelist[texturenumsurfaces++] = surface;
8258                         }
8259                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
8260                                 continue;
8261                         // render the range of surfaces as depth
8262                         if (!setup)
8263                         {
8264                                 setup = true;
8265                                 GL_ColorMask(0,0,0,0);
8266                                 GL_Color(1,1,1,1);
8267                                 GL_DepthTest(true);
8268                                 GL_BlendFunc(GL_ONE, GL_ZERO);
8269                                 GL_DepthMask(true);
8270                                 GL_AlphaTest(false);
8271                                 R_Mesh_ColorPointer(NULL, 0, 0);
8272                                 R_Mesh_ResetTextureState();
8273                                 R_SetupDepthOrShadowShader();
8274                         }
8275                         RSurf_SetupDepthAndCulling();
8276                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8277                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8278                 }
8279                 if (setup)
8280                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8281         }
8282
8283         for (i = 0;i < numsurfaces;i = j)
8284         {
8285                 j = i + 1;
8286                 surface = rsurface.modelsurfaces + surfacelist[i];
8287                 texture = surface->texture;
8288                 rsurface.texture = R_GetCurrentTexture(texture);
8289                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8290                 // scan ahead until we find a different texture
8291                 endsurface = min(i + 1024, numsurfaces);
8292                 texturenumsurfaces = 0;
8293                 texturesurfacelist[texturenumsurfaces++] = surface;
8294                 for (;j < endsurface;j++)
8295                 {
8296                         surface = rsurface.modelsurfaces + surfacelist[j];
8297                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8298                                 break;
8299                         texturesurfacelist[texturenumsurfaces++] = surface;
8300                 }
8301                 // render the range of surfaces
8302                 if (ent == r_refdef.scene.worldentity)
8303                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8304                 else
8305                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8306         }
8307         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8308         GL_AlphaTest(false);
8309 }
8310
8311 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
8312 {
8313         // transparent surfaces get pushed off into the transparent queue
8314         int surfacelistindex;
8315         const msurface_t *surface;
8316         vec3_t tempcenter, center;
8317         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8318         {
8319                 surface = texturesurfacelist[surfacelistindex];
8320                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8321                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8322                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8323                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8324                 if (queueentity->transparent_offset) // transparent offset
8325                 {
8326                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8327                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8328                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8329                 }
8330                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8331         }
8332 }
8333
8334 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
8335 {
8336         const entity_render_t *queueentity = r_refdef.scene.worldentity;
8337         CHECKGLERROR
8338         if (depthonly)
8339         {
8340                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8341                         return;
8342                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8343                         return;
8344                 RSurf_SetupDepthAndCulling();
8345                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8346                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8347         }
8348         else if (prepass)
8349         {
8350                 if (!rsurface.texture->currentnumlayers)
8351                         return;
8352                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8353                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8354                 else
8355                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8356         }
8357         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
8358         {
8359                 RSurf_SetupDepthAndCulling();
8360                 GL_AlphaTest(false);
8361                 R_Mesh_ColorPointer(NULL, 0, 0);
8362                 R_Mesh_ResetTextureState();
8363                 R_SetupGenericShader(false);
8364                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8365                 GL_DepthMask(true);
8366                 GL_BlendFunc(GL_ONE, GL_ZERO);
8367                 GL_Color(0, 0, 0, 1);
8368                 GL_DepthTest(writedepth);
8369                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8370         }
8371         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
8372         {
8373                 RSurf_SetupDepthAndCulling();
8374                 GL_AlphaTest(false);
8375                 R_Mesh_ColorPointer(NULL, 0, 0);
8376                 R_Mesh_ResetTextureState();
8377                 R_SetupGenericShader(false);
8378                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8379                 GL_DepthMask(true);
8380                 GL_BlendFunc(GL_ONE, GL_ZERO);
8381                 GL_DepthTest(true);
8382                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8383         }
8384         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8385                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8386         else if (!rsurface.texture->currentnumlayers)
8387                 return;
8388         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8389         {
8390                 // in the deferred case, transparent surfaces were queued during prepass
8391                 if (!r_shadow_usingdeferredprepass)
8392                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8393         }
8394         else
8395         {
8396                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8397                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8398         }
8399         CHECKGLERROR
8400 }
8401
8402 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8403 {
8404         int i, j;
8405         texture_t *texture;
8406         // break the surface list down into batches by texture and use of lightmapping
8407         for (i = 0;i < numsurfaces;i = j)
8408         {
8409                 j = i + 1;
8410                 // texture is the base texture pointer, rsurface.texture is the
8411                 // current frame/skin the texture is directing us to use (for example
8412                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8413                 // use skin 1 instead)
8414                 texture = surfacelist[i]->texture;
8415                 rsurface.texture = R_GetCurrentTexture(texture);
8416                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8417                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8418                 {
8419                         // if this texture is not the kind we want, skip ahead to the next one
8420                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8421                                 ;
8422                         continue;
8423                 }
8424                 // simply scan ahead until we find a different texture or lightmap state
8425                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8426                         ;
8427                 // render the range of surfaces
8428                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
8429         }
8430 }
8431
8432 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
8433 {
8434         CHECKGLERROR
8435         if (depthonly)
8436         {
8437                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8438                         return;
8439                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8440                         return;
8441                 RSurf_SetupDepthAndCulling();
8442                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8443                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8444         }
8445         else if (prepass)
8446         {
8447                 if (!rsurface.texture->currentnumlayers)
8448                         return;
8449                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8450                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8451                 else
8452                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8453         }
8454         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8455         {
8456                 RSurf_SetupDepthAndCulling();
8457                 GL_AlphaTest(false);
8458                 R_Mesh_ColorPointer(NULL, 0, 0);
8459                 R_Mesh_ResetTextureState();
8460                 R_SetupGenericShader(false);
8461                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8462                 GL_DepthMask(true);
8463                 GL_BlendFunc(GL_ONE, GL_ZERO);
8464                 GL_Color(0, 0, 0, 1);
8465                 GL_DepthTest(writedepth);
8466                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8467         }
8468         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8469         {
8470                 RSurf_SetupDepthAndCulling();
8471                 GL_AlphaTest(false);
8472                 R_Mesh_ColorPointer(NULL, 0, 0);
8473                 R_Mesh_ResetTextureState();
8474                 R_SetupGenericShader(false);
8475                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8476                 GL_DepthMask(true);
8477                 GL_BlendFunc(GL_ONE, GL_ZERO);
8478                 GL_DepthTest(true);
8479                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8480         }
8481         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8482                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8483         else if (!rsurface.texture->currentnumlayers)
8484                 return;
8485         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8486         {
8487                 // in the deferred case, transparent surfaces were queued during prepass
8488                 if (!r_shadow_usingdeferredprepass)
8489                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8490         }
8491         else
8492         {
8493                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8494                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8495         }
8496         CHECKGLERROR
8497 }
8498
8499 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8500 {
8501         int i, j;
8502         texture_t *texture;
8503         // break the surface list down into batches by texture and use of lightmapping
8504         for (i = 0;i < numsurfaces;i = j)
8505         {
8506                 j = i + 1;
8507                 // texture is the base texture pointer, rsurface.texture is the
8508                 // current frame/skin the texture is directing us to use (for example
8509                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8510                 // use skin 1 instead)
8511                 texture = surfacelist[i]->texture;
8512                 rsurface.texture = R_GetCurrentTexture(texture);
8513                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8514                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8515                 {
8516                         // if this texture is not the kind we want, skip ahead to the next one
8517                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8518                                 ;
8519                         continue;
8520                 }
8521                 // simply scan ahead until we find a different texture or lightmap state
8522                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8523                         ;
8524                 // render the range of surfaces
8525                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
8526         }
8527 }
8528
8529 float locboxvertex3f[6*4*3] =
8530 {
8531         1,0,1, 1,0,0, 1,1,0, 1,1,1,
8532         0,1,1, 0,1,0, 0,0,0, 0,0,1,
8533         1,1,1, 1,1,0, 0,1,0, 0,1,1,
8534         0,0,1, 0,0,0, 1,0,0, 1,0,1,
8535         0,0,1, 1,0,1, 1,1,1, 0,1,1,
8536         1,0,0, 0,0,0, 0,1,0, 1,1,0
8537 };
8538
8539 unsigned short locboxelements[6*2*3] =
8540 {
8541          0, 1, 2, 0, 2, 3,
8542          4, 5, 6, 4, 6, 7,
8543          8, 9,10, 8,10,11,
8544         12,13,14, 12,14,15,
8545         16,17,18, 16,18,19,
8546         20,21,22, 20,22,23
8547 };
8548
8549 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8550 {
8551         int i, j;
8552         cl_locnode_t *loc = (cl_locnode_t *)ent;
8553         vec3_t mins, size;
8554         float vertex3f[6*4*3];
8555         CHECKGLERROR
8556         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8557         GL_DepthMask(false);
8558         GL_DepthRange(0, 1);
8559         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8560         GL_DepthTest(true);
8561         GL_CullFace(GL_NONE);
8562         R_Mesh_Matrix(&identitymatrix);
8563
8564         R_Mesh_VertexPointer(vertex3f, 0, 0);
8565         R_Mesh_ColorPointer(NULL, 0, 0);
8566         R_Mesh_ResetTextureState();
8567         R_SetupGenericShader(false);
8568
8569         i = surfacelist[0];
8570         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8571                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8572                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8573                         surfacelist[0] < 0 ? 0.5f : 0.125f);
8574
8575         if (VectorCompare(loc->mins, loc->maxs))
8576         {
8577                 VectorSet(size, 2, 2, 2);
8578                 VectorMA(loc->mins, -0.5f, size, mins);
8579         }
8580         else
8581         {
8582                 VectorCopy(loc->mins, mins);
8583                 VectorSubtract(loc->maxs, loc->mins, size);
8584         }
8585
8586         for (i = 0;i < 6*4*3;)
8587                 for (j = 0;j < 3;j++, i++)
8588                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8589
8590         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8591 }
8592
8593 void R_DrawLocs(void)
8594 {
8595         int index;
8596         cl_locnode_t *loc, *nearestloc;
8597         vec3_t center;
8598         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8599         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8600         {
8601                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8602                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8603         }
8604 }
8605
8606 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8607 {
8608         if (decalsystem->decals)
8609                 Mem_Free(decalsystem->decals);
8610         memset(decalsystem, 0, sizeof(*decalsystem));
8611 }
8612
8613 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)
8614 {
8615         tridecal_t *decal;
8616         tridecal_t *decals;
8617         int i;
8618         int maxdecals;
8619
8620         // expand or initialize the system
8621         if (decalsystem->maxdecals <= decalsystem->numdecals)
8622         {
8623                 decalsystem_t old = *decalsystem;
8624                 qboolean useshortelements;
8625                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8626                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8627                 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)));
8628                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8629                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8630                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8631                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8632                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8633                 if (decalsystem->numdecals)
8634                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8635                 if (old.decals)
8636                         Mem_Free(old.decals);
8637                 for (i = 0;i < decalsystem->maxdecals*3;i++)
8638                         decalsystem->element3i[i] = i;
8639                 if (useshortelements)
8640                         for (i = 0;i < decalsystem->maxdecals*3;i++)
8641                                 decalsystem->element3s[i] = i;
8642         }
8643
8644         // grab a decal and search for another free slot for the next one
8645         maxdecals = decalsystem->maxdecals;
8646         decals = decalsystem->decals;
8647         decal = decalsystem->decals + (i = decalsystem->freedecal++);
8648         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8649                 ;
8650         decalsystem->freedecal = i;
8651         if (decalsystem->numdecals <= i)
8652                 decalsystem->numdecals = i + 1;
8653
8654         // initialize the decal
8655         decal->lived = 0;
8656         decal->triangleindex = triangleindex;
8657         decal->surfaceindex = surfaceindex;
8658         decal->decalsequence = decalsequence;
8659         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8660         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8661         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8662         decal->color4ub[0][3] = 255;
8663         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8664         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8665         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8666         decal->color4ub[1][3] = 255;
8667         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8668         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8669         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8670         decal->color4ub[2][3] = 255;
8671         decal->vertex3f[0][0] = v0[0];
8672         decal->vertex3f[0][1] = v0[1];
8673         decal->vertex3f[0][2] = v0[2];
8674         decal->vertex3f[1][0] = v1[0];
8675         decal->vertex3f[1][1] = v1[1];
8676         decal->vertex3f[1][2] = v1[2];
8677         decal->vertex3f[2][0] = v2[0];
8678         decal->vertex3f[2][1] = v2[1];
8679         decal->vertex3f[2][2] = v2[2];
8680         decal->texcoord2f[0][0] = t0[0];
8681         decal->texcoord2f[0][1] = t0[1];
8682         decal->texcoord2f[1][0] = t1[0];
8683         decal->texcoord2f[1][1] = t1[1];
8684         decal->texcoord2f[2][0] = t2[0];
8685         decal->texcoord2f[2][1] = t2[1];
8686 }
8687
8688 extern cvar_t cl_decals_bias;
8689 extern cvar_t cl_decals_models;
8690 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8691 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)
8692 {
8693         matrix4x4_t projection;
8694         decalsystem_t *decalsystem;
8695         qboolean dynamic;
8696         dp_model_t *model;
8697         const float *vertex3f;
8698         const msurface_t *surface;
8699         const msurface_t *surfaces;
8700         const int *surfacelist;
8701         const texture_t *texture;
8702         int numvertices;
8703         int numtriangles;
8704         int numsurfacelist;
8705         int surfacelistindex;
8706         int surfaceindex;
8707         int triangleindex;
8708         int decalsurfaceindex;
8709         int cornerindex;
8710         int index;
8711         int numpoints;
8712         const int *e;
8713         float localorigin[3];
8714         float localnormal[3];
8715         float localmins[3];
8716         float localmaxs[3];
8717         float localsize;
8718         float ilocalsize;
8719         float v[9][3];
8720         float tc[9][2];
8721         float c[9][4];
8722         //float normal[3];
8723         float planes[6][4];
8724         float f;
8725         float points[2][9][3];
8726         float angles[3];
8727         float temp[3];
8728
8729         decalsystem = &ent->decalsystem;
8730         model = ent->model;
8731         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8732         {
8733                 R_DecalSystem_Reset(&ent->decalsystem);
8734                 return;
8735         }
8736
8737         if (!model->brush.data_nodes && !cl_decals_models.integer)
8738         {
8739                 if (decalsystem->model)
8740                         R_DecalSystem_Reset(decalsystem);
8741                 return;
8742         }
8743
8744         if (decalsystem->model != model)
8745                 R_DecalSystem_Reset(decalsystem);
8746         decalsystem->model = model;
8747
8748         RSurf_ActiveModelEntity(ent, false, false, false);
8749
8750         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8751         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8752         VectorNormalize(localnormal);
8753         localsize = worldsize*rsurface.inversematrixscale;
8754         ilocalsize = 1.0f / localsize;
8755         localmins[0] = localorigin[0] - localsize;
8756         localmins[1] = localorigin[1] - localsize;
8757         localmins[2] = localorigin[2] - localsize;
8758         localmaxs[0] = localorigin[0] + localsize;
8759         localmaxs[1] = localorigin[1] + localsize;
8760         localmaxs[2] = localorigin[2] + localsize;
8761
8762         //VectorCopy(localnormal, planes[4]);
8763         //VectorVectors(planes[4], planes[2], planes[0]);
8764         AnglesFromVectors(angles, localnormal, NULL, false);
8765         AngleVectors(angles, planes[0], planes[2], planes[4]);
8766         VectorNegate(planes[0], planes[1]);
8767         VectorNegate(planes[2], planes[3]);
8768         VectorNegate(planes[4], planes[5]);
8769         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8770         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8771         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8772         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8773         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8774         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8775
8776 #if 1
8777 // works
8778 {
8779         matrix4x4_t forwardprojection;
8780         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8781         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8782 }
8783 #else
8784 // broken
8785 {
8786         float projectionvector[4][3];
8787         VectorScale(planes[0], ilocalsize, projectionvector[0]);
8788         VectorScale(planes[2], ilocalsize, projectionvector[1]);
8789         VectorScale(planes[4], ilocalsize, projectionvector[2]);
8790         projectionvector[0][0] = planes[0][0] * ilocalsize;
8791         projectionvector[0][1] = planes[1][0] * ilocalsize;
8792         projectionvector[0][2] = planes[2][0] * ilocalsize;
8793         projectionvector[1][0] = planes[0][1] * ilocalsize;
8794         projectionvector[1][1] = planes[1][1] * ilocalsize;
8795         projectionvector[1][2] = planes[2][1] * ilocalsize;
8796         projectionvector[2][0] = planes[0][2] * ilocalsize;
8797         projectionvector[2][1] = planes[1][2] * ilocalsize;
8798         projectionvector[2][2] = planes[2][2] * ilocalsize;
8799         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8800         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8801         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8802         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8803 }
8804 #endif
8805
8806         dynamic = model->surfmesh.isanimated;
8807         vertex3f = rsurface.modelvertex3f;
8808         numsurfacelist = model->nummodelsurfaces;
8809         surfacelist = model->sortedmodelsurfaces;
8810         surfaces = model->data_surfaces;
8811         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8812         {
8813                 surfaceindex = surfacelist[surfacelistindex];
8814                 surface = surfaces + surfaceindex;
8815                 // skip transparent surfaces
8816                 texture = surface->texture;
8817                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8818                         continue;
8819                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8820                         continue;
8821                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8822                         continue;
8823                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8824                 numvertices = surface->num_vertices;
8825                 numtriangles = surface->num_triangles;
8826                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8827                 {
8828                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
8829                         {
8830                                 index = 3*e[cornerindex];
8831                                 VectorCopy(vertex3f + index, v[cornerindex]);
8832                         }
8833                         // cull backfaces
8834                         //TriangleNormal(v[0], v[1], v[2], normal);
8835                         //if (DotProduct(normal, localnormal) < 0.0f)
8836                         //      continue;
8837                         // clip by each of the box planes formed from the projection matrix
8838                         // if anything survives, we emit the decal
8839                         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]);
8840                         if (numpoints < 3)
8841                                 continue;
8842                         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]);
8843                         if (numpoints < 3)
8844                                 continue;
8845                         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]);
8846                         if (numpoints < 3)
8847                                 continue;
8848                         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]);
8849                         if (numpoints < 3)
8850                                 continue;
8851                         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]);
8852                         if (numpoints < 3)
8853                                 continue;
8854                         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]);
8855                         if (numpoints < 3)
8856                                 continue;
8857                         // some part of the triangle survived, so we have to accept it...
8858                         if (dynamic)
8859                         {
8860                                 // dynamic always uses the original triangle
8861                                 numpoints = 3;
8862                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8863                                 {
8864                                         index = 3*e[cornerindex];
8865                                         VectorCopy(vertex3f + index, v[cornerindex]);
8866                                 }
8867                         }
8868                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8869                         {
8870                                 // convert vertex positions to texcoords
8871                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8872                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8873                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8874                                 // calculate distance fade from the projection origin
8875                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8876                                 f = bound(0.0f, f, 1.0f);
8877                                 c[cornerindex][0] = r * f;
8878                                 c[cornerindex][1] = g * f;
8879                                 c[cornerindex][2] = b * f;
8880                                 c[cornerindex][3] = 1.0f;
8881                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8882                         }
8883                         if (dynamic)
8884                                 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);
8885                         else
8886                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8887                                         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);
8888                 }
8889         }
8890 }
8891
8892 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8893 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)
8894 {
8895         int renderentityindex;
8896         float worldmins[3];
8897         float worldmaxs[3];
8898         entity_render_t *ent;
8899
8900         if (!cl_decals_newsystem.integer)
8901                 return;
8902
8903         worldmins[0] = worldorigin[0] - worldsize;
8904         worldmins[1] = worldorigin[1] - worldsize;
8905         worldmins[2] = worldorigin[2] - worldsize;
8906         worldmaxs[0] = worldorigin[0] + worldsize;
8907         worldmaxs[1] = worldorigin[1] + worldsize;
8908         worldmaxs[2] = worldorigin[2] + worldsize;
8909
8910         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8911
8912         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8913         {
8914                 ent = r_refdef.scene.entities[renderentityindex];
8915                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8916                         continue;
8917
8918                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8919         }
8920 }
8921
8922 typedef struct r_decalsystem_splatqueue_s
8923 {
8924         vec3_t worldorigin;
8925         vec3_t worldnormal;
8926         float color[4];
8927         float tcrange[4];
8928         float worldsize;
8929         int decalsequence;
8930 }
8931 r_decalsystem_splatqueue_t;
8932
8933 int r_decalsystem_numqueued = 0;
8934 #define MAX_DECALSYSTEM_QUEUE 1024
8935 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8936
8937 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)
8938 {
8939         r_decalsystem_splatqueue_t *queue;
8940
8941         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8942                 return;
8943
8944         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8945         VectorCopy(worldorigin, queue->worldorigin);
8946         VectorCopy(worldnormal, queue->worldnormal);
8947         Vector4Set(queue->color, r, g, b, a);
8948         Vector4Set(queue->tcrange, s1, t1, s2, t2);
8949         queue->worldsize = worldsize;
8950         queue->decalsequence = cl.decalsequence++;
8951 }
8952
8953 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8954 {
8955         int i;
8956         r_decalsystem_splatqueue_t *queue;
8957
8958         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8959                 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);
8960         r_decalsystem_numqueued = 0;
8961 }
8962
8963 extern cvar_t cl_decals_max;
8964 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8965 {
8966         int i;
8967         decalsystem_t *decalsystem = &ent->decalsystem;
8968         int numdecals;
8969         int killsequence;
8970         tridecal_t *decal;
8971         float frametime;
8972         float lifetime;
8973
8974         if (!decalsystem->numdecals)
8975                 return;
8976
8977         if (r_showsurfaces.integer)
8978                 return;
8979
8980         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8981         {
8982                 R_DecalSystem_Reset(decalsystem);
8983                 return;
8984         }
8985
8986         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8987         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8988
8989         if (decalsystem->lastupdatetime)
8990                 frametime = (cl.time - decalsystem->lastupdatetime);
8991         else
8992                 frametime = 0;
8993         decalsystem->lastupdatetime = cl.time;
8994         decal = decalsystem->decals;
8995         numdecals = decalsystem->numdecals;
8996
8997         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8998         {
8999                 if (decal->color4ub[0][3])
9000                 {
9001                         decal->lived += frametime;
9002                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
9003                         {
9004                                 memset(decal, 0, sizeof(*decal));
9005                                 if (decalsystem->freedecal > i)
9006                                         decalsystem->freedecal = i;
9007                         }
9008                 }
9009         }
9010         decal = decalsystem->decals;
9011         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
9012                 numdecals--;
9013
9014         // collapse the array by shuffling the tail decals into the gaps
9015         for (;;)
9016         {
9017                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
9018                         decalsystem->freedecal++;
9019                 if (decalsystem->freedecal == numdecals)
9020                         break;
9021                 decal[decalsystem->freedecal] = decal[--numdecals];
9022         }
9023
9024         decalsystem->numdecals = numdecals;
9025
9026         if (numdecals <= 0)
9027         {
9028                 // if there are no decals left, reset decalsystem
9029                 R_DecalSystem_Reset(decalsystem);
9030         }
9031 }
9032
9033 extern skinframe_t *decalskinframe;
9034 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9035 {
9036         int i;
9037         decalsystem_t *decalsystem = &ent->decalsystem;
9038         int numdecals;
9039         tridecal_t *decal;
9040         float fadedelay;
9041         float faderate;
9042         float alpha;
9043         float *v3f;
9044         float *c4f;
9045         float *t2f;
9046         const int *e;
9047         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9048         int numtris = 0;
9049
9050         numdecals = decalsystem->numdecals;
9051         if (!numdecals)
9052                 return;
9053
9054         if (r_showsurfaces.integer)
9055                 return;
9056
9057         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9058         {
9059                 R_DecalSystem_Reset(decalsystem);
9060                 return;
9061         }
9062
9063         // if the model is static it doesn't matter what value we give for
9064         // wantnormals and wanttangents, so this logic uses only rules applicable
9065         // to a model, knowing that they are meaningless otherwise
9066         if (ent == r_refdef.scene.worldentity)
9067                 RSurf_ActiveWorldEntity();
9068         else
9069                 RSurf_ActiveModelEntity(ent, false, false, false);
9070
9071         decalsystem->lastupdatetime = cl.time;
9072         decal = decalsystem->decals;
9073
9074         fadedelay = cl_decals_time.value;
9075         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9076
9077         // update vertex positions for animated models
9078         v3f = decalsystem->vertex3f;
9079         c4f = decalsystem->color4f;
9080         t2f = decalsystem->texcoord2f;
9081         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9082         {
9083                 if (!decal->color4ub[0][3])
9084                         continue;
9085
9086                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9087                         continue;
9088
9089                 // update color values for fading decals
9090                 if (decal->lived >= cl_decals_time.value)
9091                 {
9092                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9093                         alpha *= (1.0f/255.0f);
9094                 }
9095                 else
9096                         alpha = 1.0f/255.0f;
9097
9098                 c4f[ 0] = decal->color4ub[0][0] * alpha;
9099                 c4f[ 1] = decal->color4ub[0][1] * alpha;
9100                 c4f[ 2] = decal->color4ub[0][2] * alpha;
9101                 c4f[ 3] = 1;
9102                 c4f[ 4] = decal->color4ub[1][0] * alpha;
9103                 c4f[ 5] = decal->color4ub[1][1] * alpha;
9104                 c4f[ 6] = decal->color4ub[1][2] * alpha;
9105                 c4f[ 7] = 1;
9106                 c4f[ 8] = decal->color4ub[2][0] * alpha;
9107                 c4f[ 9] = decal->color4ub[2][1] * alpha;
9108                 c4f[10] = decal->color4ub[2][2] * alpha;
9109                 c4f[11] = 1;
9110
9111                 t2f[0] = decal->texcoord2f[0][0];
9112                 t2f[1] = decal->texcoord2f[0][1];
9113                 t2f[2] = decal->texcoord2f[1][0];
9114                 t2f[3] = decal->texcoord2f[1][1];
9115                 t2f[4] = decal->texcoord2f[2][0];
9116                 t2f[5] = decal->texcoord2f[2][1];
9117
9118                 // update vertex positions for animated models
9119                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9120                 {
9121                         e = rsurface.modelelement3i + 3*decal->triangleindex;
9122                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9123                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9124                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9125                 }
9126                 else
9127                 {
9128                         VectorCopy(decal->vertex3f[0], v3f);
9129                         VectorCopy(decal->vertex3f[1], v3f + 3);
9130                         VectorCopy(decal->vertex3f[2], v3f + 6);
9131                 }
9132
9133                 v3f += 9;
9134                 c4f += 12;
9135                 t2f += 6;
9136                 numtris++;
9137         }
9138
9139         if (numtris > 0)
9140         {
9141                 r_refdef.stats.drawndecals += numtris;
9142
9143                 if (r_refdef.fogenabled)
9144                 {
9145                         switch(vid.renderpath)
9146                         {
9147                         case RENDERPATH_GL20:
9148                         case RENDERPATH_GL13:
9149                         case RENDERPATH_GL11:
9150                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
9151                                 {
9152                                         alpha = RSurf_FogVertex(v3f);
9153                                         c4f[0] *= alpha;
9154                                         c4f[1] *= alpha;
9155                                         c4f[2] *= alpha;
9156                                 }
9157                                 break;
9158                         }
9159                 }
9160
9161                 // now render the decals all at once
9162                 // (this assumes they all use one particle font texture!)
9163                 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);
9164                 R_Mesh_ResetTextureState();
9165                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9166                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9167                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9168                 R_SetupGenericShader(true);
9169                 GL_DepthMask(false);
9170                 GL_DepthRange(0, 1);
9171                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9172                 GL_DepthTest(true);
9173                 GL_CullFace(GL_NONE);
9174                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9175                 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
9176                 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
9177                 GL_LockArrays(0, numtris * 3);
9178                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9179                 GL_LockArrays(0, 0);
9180         }
9181 }
9182
9183 static void R_DrawModelDecals(void)
9184 {
9185         int i, numdecals;
9186
9187         // fade faster when there are too many decals
9188         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9189         for (i = 0;i < r_refdef.scene.numentities;i++)
9190                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9191
9192         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9193         for (i = 0;i < r_refdef.scene.numentities;i++)
9194                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9195                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9196
9197         R_DecalSystem_ApplySplatEntitiesQueue();
9198
9199         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9200         for (i = 0;i < r_refdef.scene.numentities;i++)
9201                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9202
9203         r_refdef.stats.totaldecals += numdecals;
9204
9205         if (r_showsurfaces.integer)
9206                 return;
9207
9208         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9209
9210         for (i = 0;i < r_refdef.scene.numentities;i++)
9211         {
9212                 if (!r_refdef.viewcache.entityvisible[i])
9213                         continue;
9214                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9215                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9216         }
9217 }
9218
9219 void R_DrawDebugModel(void)
9220 {
9221         entity_render_t *ent = rsurface.entity;
9222         int i, j, k, l, flagsmask;
9223         const int *elements;
9224         q3mbrush_t *brush;
9225         const msurface_t *surface;
9226         dp_model_t *model = ent->model;
9227         vec3_t v;
9228
9229         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9230
9231         R_Mesh_ColorPointer(NULL, 0, 0);
9232         R_Mesh_ResetTextureState();
9233         R_SetupGenericShader(false);
9234         GL_DepthRange(0, 1);
9235         GL_DepthTest(!r_showdisabledepthtest.integer);
9236         GL_DepthMask(false);
9237         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9238
9239         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
9240         {
9241                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9242                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
9243                 {
9244                         if (brush->colbrushf && brush->colbrushf->numtriangles)
9245                         {
9246                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
9247                                 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);
9248                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
9249                         }
9250                 }
9251                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
9252                 {
9253                         if (surface->num_collisiontriangles)
9254                         {
9255                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
9256                                 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);
9257                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
9258                         }
9259                 }
9260         }
9261
9262         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9263
9264         if (r_showtris.integer || r_shownormals.integer)
9265         {
9266                 if (r_showdisabledepthtest.integer)
9267                 {
9268                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9269                         GL_DepthMask(false);
9270                 }
9271                 else
9272                 {
9273                         GL_BlendFunc(GL_ONE, GL_ZERO);
9274                         GL_DepthMask(true);
9275                 }
9276                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9277                 {
9278                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9279                                 continue;
9280                         rsurface.texture = R_GetCurrentTexture(surface->texture);
9281                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9282                         {
9283                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
9284                                 if (r_showtris.value > 0)
9285                                 {
9286                                         if (!rsurface.texture->currentlayers->depthmask)
9287                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9288                                         else if (ent == r_refdef.scene.worldentity)
9289                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9290                                         else
9291                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9292                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
9293                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
9294                                         R_Mesh_ColorPointer(NULL, 0, 0);
9295                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
9296                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9297                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
9298                                         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);
9299                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9300                                         CHECKGLERROR
9301                                 }
9302                                 if (r_shownormals.value < 0)
9303                                 {
9304                                         qglBegin(GL_LINES);
9305                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9306                                         {
9307                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
9308                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9309                                                 qglVertex3f(v[0], v[1], v[2]);
9310                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
9311                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9312                                                 qglVertex3f(v[0], v[1], v[2]);
9313                                         }
9314                                         qglEnd();
9315                                         CHECKGLERROR
9316                                 }
9317                                 if (r_shownormals.value > 0)
9318                                 {
9319                                         qglBegin(GL_LINES);
9320                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9321                                         {
9322                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
9323                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9324                                                 qglVertex3f(v[0], v[1], v[2]);
9325                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
9326                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9327                                                 qglVertex3f(v[0], v[1], v[2]);
9328                                         }
9329                                         qglEnd();
9330                                         CHECKGLERROR
9331                                         qglBegin(GL_LINES);
9332                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9333                                         {
9334                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
9335                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
9336                                                 qglVertex3f(v[0], v[1], v[2]);
9337                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
9338                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9339                                                 qglVertex3f(v[0], v[1], v[2]);
9340                                         }
9341                                         qglEnd();
9342                                         CHECKGLERROR
9343                                         qglBegin(GL_LINES);
9344                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9345                                         {
9346                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
9347                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9348                                                 qglVertex3f(v[0], v[1], v[2]);
9349                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
9350                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9351                                                 qglVertex3f(v[0], v[1], v[2]);
9352                                         }
9353                                         qglEnd();
9354                                         CHECKGLERROR
9355                                 }
9356                         }
9357                 }
9358                 rsurface.texture = NULL;
9359         }
9360 }
9361
9362 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
9363 int r_maxsurfacelist = 0;
9364 const msurface_t **r_surfacelist = NULL;
9365 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9366 {
9367         int i, j, endj, f, flagsmask;
9368         texture_t *t;
9369         dp_model_t *model = r_refdef.scene.worldmodel;
9370         msurface_t *surfaces;
9371         unsigned char *update;
9372         int numsurfacelist = 0;
9373         if (model == NULL)
9374                 return;
9375
9376         if (r_maxsurfacelist < model->num_surfaces)
9377         {
9378                 r_maxsurfacelist = model->num_surfaces;
9379                 if (r_surfacelist)
9380                         Mem_Free((msurface_t**)r_surfacelist);
9381                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9382         }
9383
9384         RSurf_ActiveWorldEntity();
9385
9386         surfaces = model->data_surfaces;
9387         update = model->brushq1.lightmapupdateflags;
9388
9389         // update light styles on this submodel
9390         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9391         {
9392                 model_brush_lightstyleinfo_t *style;
9393                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9394                 {
9395                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
9396                         {
9397                                 int *list = style->surfacelist;
9398                                 style->value = r_refdef.scene.lightstylevalue[style->style];
9399                                 for (j = 0;j < style->numsurfaces;j++)
9400                                         update[list[j]] = true;
9401                         }
9402                 }
9403         }
9404
9405         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9406
9407         if (debug)
9408         {
9409                 R_DrawDebugModel();
9410                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9411                 return;
9412         }
9413
9414         f = 0;
9415         t = NULL;
9416         rsurface.uselightmaptexture = false;
9417         rsurface.texture = NULL;
9418         rsurface.rtlight = NULL;
9419         numsurfacelist = 0;
9420         // add visible surfaces to draw list
9421         for (i = 0;i < model->nummodelsurfaces;i++)
9422         {
9423                 j = model->sortedmodelsurfaces[i];
9424                 if (r_refdef.viewcache.world_surfacevisible[j])
9425                         r_surfacelist[numsurfacelist++] = surfaces + j;
9426         }
9427         // update lightmaps if needed
9428         if (update)
9429                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9430                         if (r_refdef.viewcache.world_surfacevisible[j])
9431                                 if (update[j])
9432                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9433         // don't do anything if there were no surfaces
9434         if (!numsurfacelist)
9435         {
9436                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9437                 return;
9438         }
9439         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9440         GL_AlphaTest(false);
9441
9442         // add to stats if desired
9443         if (r_speeds.integer && !skysurfaces && !depthonly)
9444         {
9445                 r_refdef.stats.world_surfaces += numsurfacelist;
9446                 for (j = 0;j < numsurfacelist;j++)
9447                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9448         }
9449
9450         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9451 }
9452
9453 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9454 {
9455         int i, j, endj, f, flagsmask;
9456         texture_t *t;
9457         dp_model_t *model = ent->model;
9458         msurface_t *surfaces;
9459         unsigned char *update;
9460         int numsurfacelist = 0;
9461         if (model == NULL)
9462                 return;
9463
9464         if (r_maxsurfacelist < model->num_surfaces)
9465         {
9466                 r_maxsurfacelist = model->num_surfaces;
9467                 if (r_surfacelist)
9468                         Mem_Free((msurface_t **)r_surfacelist);
9469                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9470         }
9471
9472         // if the model is static it doesn't matter what value we give for
9473         // wantnormals and wanttangents, so this logic uses only rules applicable
9474         // to a model, knowing that they are meaningless otherwise
9475         if (ent == r_refdef.scene.worldentity)
9476                 RSurf_ActiveWorldEntity();
9477         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9478                 RSurf_ActiveModelEntity(ent, false, false, false);
9479         else if (prepass)
9480                 RSurf_ActiveModelEntity(ent, true, true, true);
9481         else if (depthonly)
9482                 RSurf_ActiveModelEntity(ent, false, false, false);
9483         else
9484         {
9485                 switch (vid.renderpath)
9486                 {
9487                 case RENDERPATH_GL20:
9488                         RSurf_ActiveModelEntity(ent, true, true, false);
9489                         break;
9490                 case RENDERPATH_GL13:
9491                 case RENDERPATH_GL11:
9492                         RSurf_ActiveModelEntity(ent, true, false, false);
9493                         break;
9494                 }
9495         }
9496
9497         surfaces = model->data_surfaces;
9498         update = model->brushq1.lightmapupdateflags;
9499
9500         // update light styles
9501         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9502         {
9503                 model_brush_lightstyleinfo_t *style;
9504                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9505                 {
9506                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
9507                         {
9508                                 int *list = style->surfacelist;
9509                                 style->value = r_refdef.scene.lightstylevalue[style->style];
9510                                 for (j = 0;j < style->numsurfaces;j++)
9511                                         update[list[j]] = true;
9512                         }
9513                 }
9514         }
9515
9516         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9517
9518         if (debug)
9519         {
9520                 R_DrawDebugModel();
9521                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9522                 return;
9523         }
9524
9525         f = 0;
9526         t = NULL;
9527         rsurface.uselightmaptexture = false;
9528         rsurface.texture = NULL;
9529         rsurface.rtlight = NULL;
9530         numsurfacelist = 0;
9531         // add visible surfaces to draw list
9532         for (i = 0;i < model->nummodelsurfaces;i++)
9533                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9534         // don't do anything if there were no surfaces
9535         if (!numsurfacelist)
9536         {
9537                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9538                 return;
9539         }
9540         // update lightmaps if needed
9541         if (update)
9542                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9543                         if (update[j])
9544                                 R_BuildLightMap(ent, surfaces + j);
9545         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9546         GL_AlphaTest(false);
9547
9548         // add to stats if desired
9549         if (r_speeds.integer && !skysurfaces && !depthonly)
9550         {
9551                 r_refdef.stats.entities_surfaces += numsurfacelist;
9552                 for (j = 0;j < numsurfacelist;j++)
9553                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9554         }
9555
9556         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9557 }
9558
9559 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
9560 {
9561         static texture_t texture;
9562         static msurface_t surface;
9563         const msurface_t *surfacelist = &surface;
9564
9565         // fake enough texture and surface state to render this geometry
9566
9567         texture.update_lastrenderframe = -1; // regenerate this texture
9568         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9569         texture.currentskinframe = skinframe;
9570         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9571         texture.specularscalemod = 1;
9572         texture.specularpowermod = 1;
9573
9574         surface.texture = &texture;
9575         surface.num_triangles = numtriangles;
9576         surface.num_firsttriangle = firsttriangle;
9577         surface.num_vertices = numvertices;
9578         surface.num_firstvertex = firstvertex;
9579
9580         // now render it
9581         rsurface.texture = R_GetCurrentTexture(surface.texture);
9582         rsurface.uselightmaptexture = false;
9583         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
9584 }
9585
9586 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)
9587 {
9588         static msurface_t surface;
9589         const msurface_t *surfacelist = &surface;
9590
9591         // fake enough texture and surface state to render this geometry
9592
9593         surface.texture = texture;
9594         surface.num_triangles = numtriangles;
9595         surface.num_firsttriangle = firsttriangle;
9596         surface.num_vertices = numvertices;
9597         surface.num_firstvertex = firstvertex;
9598
9599         // now render it
9600         rsurface.texture = R_GetCurrentTexture(surface.texture);
9601         rsurface.uselightmaptexture = false;
9602         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
9603 }