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