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