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