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