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