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