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