changed texture formats from RGBA to BGRA, yes this is a massive change,
[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 //
32 // screen size info
33 //
34 r_refdef_t r_refdef;
35 r_view_t r_view;
36 r_viewcache_t r_viewcache;
37
38 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "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"};
39 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
40 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
41 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)"};
42 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
43 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
44 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"};
45 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"};
46 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
47 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"};
48 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"};
49 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"};
50 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
51 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
52 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
53 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
54 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
55 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
56 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
57 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
58 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
59 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
60 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
61 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
62 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
63 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
64 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
65 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"};
66 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"};
67
68 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
69 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
70 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
71 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
72 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
73 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
74 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
75
76 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)"};
77
78 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
79 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
80 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
81 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
82 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)"};
83 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
84
85 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)"};
86 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
87 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"};
88 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
89 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
90
91 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
92 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
93 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
94
95 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
96 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
97 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
98 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
99 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
100 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
101 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
102
103 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
104 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
105 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
106 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)"};
107
108 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"};
109
110 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"};
111
112 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
113
114 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
115 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
116 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"};
117 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
118 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
119 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
120
121 extern qboolean v_flipped_state;
122
123 typedef struct r_glsl_bloomshader_s
124 {
125         int program;
126         int loc_Texture_Bloom;
127 }
128 r_glsl_bloomshader_t;
129
130 static struct r_bloomstate_s
131 {
132         qboolean enabled;
133         qboolean hdr;
134
135         int bloomwidth, bloomheight;
136
137         int screentexturewidth, screentextureheight;
138         rtexture_t *texture_screen;
139
140         int bloomtexturewidth, bloomtextureheight;
141         rtexture_t *texture_bloom;
142
143         r_glsl_bloomshader_t *shader;
144
145         // arrays for rendering the screen passes
146         float screentexcoord2f[8];
147         float bloomtexcoord2f[8];
148         float offsettexcoord2f[8];
149 }
150 r_bloomstate;
151
152 typedef struct r_waterstate_waterplane_s
153 {
154         rtexture_t *texture_refraction;
155         rtexture_t *texture_reflection;
156         mplane_t plane;
157         int materialflags; // combined flags of all water surfaces on this plane
158         unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
159         qboolean pvsvalid;
160 }
161 r_waterstate_waterplane_t;
162
163 #define MAX_WATERPLANES 16
164
165 static struct r_waterstate_s
166 {
167         qboolean enabled;
168
169         qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
170
171         int waterwidth, waterheight;
172         int texturewidth, textureheight;
173
174         int maxwaterplanes; // same as MAX_WATERPLANES
175         int numwaterplanes;
176         r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
177
178         float screenscale[2];
179         float screencenter[2];
180 }
181 r_waterstate;
182
183 // shadow volume bsp struct with automatically growing nodes buffer
184 svbsp_t r_svbsp;
185
186 rtexture_t *r_texture_blanknormalmap;
187 rtexture_t *r_texture_white;
188 rtexture_t *r_texture_grey128;
189 rtexture_t *r_texture_black;
190 rtexture_t *r_texture_notexture;
191 rtexture_t *r_texture_whitecube;
192 rtexture_t *r_texture_normalizationcube;
193 rtexture_t *r_texture_fogattenuation;
194 //rtexture_t *r_texture_fogintensity;
195
196 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
197 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
198
199 // vertex coordinates for a quad that covers the screen exactly
200 const static float r_screenvertex3f[12] =
201 {
202         0, 0, 0,
203         1, 0, 0,
204         1, 1, 0,
205         0, 1, 0
206 };
207
208 extern void R_DrawModelShadows(void);
209
210 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
211 {
212         int i;
213         for (i = 0;i < verts;i++)
214         {
215                 out[0] = in[0] * r;
216                 out[1] = in[1] * g;
217                 out[2] = in[2] * b;
218                 out[3] = in[3];
219                 in += 4;
220                 out += 4;
221         }
222 }
223
224 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
225 {
226         int i;
227         for (i = 0;i < verts;i++)
228         {
229                 out[0] = r;
230                 out[1] = g;
231                 out[2] = b;
232                 out[3] = a;
233                 out += 4;
234         }
235 }
236
237 // FIXME: move this to client?
238 void FOG_clear(void)
239 {
240         if (gamemode == GAME_NEHAHRA)
241         {
242                 Cvar_Set("gl_fogenable", "0");
243                 Cvar_Set("gl_fogdensity", "0.2");
244                 Cvar_Set("gl_fogred", "0.3");
245                 Cvar_Set("gl_foggreen", "0.3");
246                 Cvar_Set("gl_fogblue", "0.3");
247         }
248         r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
249 }
250
251 float FogPoint_World(const vec3_t p)
252 {
253         unsigned int fogmasktableindex = (unsigned int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
254         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
255 }
256
257 float FogPoint_Model(const vec3_t p)
258 {
259         unsigned int fogmasktableindex = (unsigned int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
260         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
261 }
262
263 static void R_BuildBlankTextures(void)
264 {
265         unsigned char data[4];
266         data[2] = 128; // normal X
267         data[1] = 128; // normal Y
268         data[0] = 255; // normal Z
269         data[3] = 128; // height
270         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE, NULL);
271         data[0] = 255;
272         data[1] = 255;
273         data[2] = 255;
274         data[3] = 255;
275         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE, NULL);
276         data[0] = 128;
277         data[1] = 128;
278         data[2] = 128;
279         data[3] = 255;
280         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE, NULL);
281         data[0] = 0;
282         data[1] = 0;
283         data[2] = 0;
284         data[3] = 255;
285         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE, NULL);
286 }
287
288 static void R_BuildNoTexture(void)
289 {
290         int x, y;
291         unsigned char pix[16][16][4];
292         // this makes a light grey/dark grey checkerboard texture
293         for (y = 0;y < 16;y++)
294         {
295                 for (x = 0;x < 16;x++)
296                 {
297                         if ((y < 8) ^ (x < 8))
298                         {
299                                 pix[y][x][0] = 128;
300                                 pix[y][x][1] = 128;
301                                 pix[y][x][2] = 128;
302                                 pix[y][x][3] = 255;
303                         }
304                         else
305                         {
306                                 pix[y][x][0] = 64;
307                                 pix[y][x][1] = 64;
308                                 pix[y][x][2] = 64;
309                                 pix[y][x][3] = 255;
310                         }
311                 }
312         }
313         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP, NULL);
314 }
315
316 static void R_BuildWhiteCube(void)
317 {
318         unsigned char data[6*1*1*4];
319         memset(data, 255, sizeof(data));
320         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
321 }
322
323 static void R_BuildNormalizationCube(void)
324 {
325         int x, y, side;
326         vec3_t v;
327         vec_t s, t, intensity;
328 #define NORMSIZE 64
329         unsigned char data[6][NORMSIZE][NORMSIZE][4];
330         for (side = 0;side < 6;side++)
331         {
332                 for (y = 0;y < NORMSIZE;y++)
333                 {
334                         for (x = 0;x < NORMSIZE;x++)
335                         {
336                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
337                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
338                                 switch(side)
339                                 {
340                                 default:
341                                 case 0:
342                                         v[0] = 1;
343                                         v[1] = -t;
344                                         v[2] = -s;
345                                         break;
346                                 case 1:
347                                         v[0] = -1;
348                                         v[1] = -t;
349                                         v[2] = s;
350                                         break;
351                                 case 2:
352                                         v[0] = s;
353                                         v[1] = 1;
354                                         v[2] = t;
355                                         break;
356                                 case 3:
357                                         v[0] = s;
358                                         v[1] = -1;
359                                         v[2] = -t;
360                                         break;
361                                 case 4:
362                                         v[0] = s;
363                                         v[1] = -t;
364                                         v[2] = 1;
365                                         break;
366                                 case 5:
367                                         v[0] = -s;
368                                         v[1] = -t;
369                                         v[2] = -1;
370                                         break;
371                                 }
372                                 intensity = 127.0f / sqrt(DotProduct(v, v));
373                                 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
374                                 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
375                                 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
376                                 data[side][y][x][3] = 255;
377                         }
378                 }
379         }
380         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
381 }
382
383 static void R_BuildFogTexture(void)
384 {
385         int x, b;
386 #define FOGWIDTH 64
387         unsigned char data1[FOGWIDTH][4];
388         //unsigned char data2[FOGWIDTH][4];
389         for (x = 0;x < FOGWIDTH;x++)
390         {
391                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
392                 data1[x][0] = b;
393                 data1[x][1] = b;
394                 data1[x][2] = b;
395                 data1[x][3] = 255;
396                 //data2[x][0] = 255 - b;
397                 //data2[x][1] = 255 - b;
398                 //data2[x][2] = 255 - b;
399                 //data2[x][3] = 255;
400         }
401         r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
402         //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
403 }
404
405 static const char *builtinshaderstring =
406 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
407 "// written by Forest 'LordHavoc' Hale\n"
408 "\n"
409 "// common definitions between vertex shader and fragment shader:\n"
410 "\n"
411 "#ifdef __GLSL_CG_DATA_TYPES\n"
412 "# define myhalf half\n"
413 "# define myhvec2 hvec2\n"
414 "# define myhvec3 hvec3\n"
415 "# define myhvec4 hvec4\n"
416 "#else\n"
417 "# define myhalf float\n"
418 "# define myhvec2 vec2\n"
419 "# define myhvec3 vec3\n"
420 "# define myhvec4 vec4\n"
421 "#endif\n"
422 "\n"
423 "varying vec2 TexCoord;\n"
424 "varying vec2 TexCoordLightmap;\n"
425 "\n"
426 "//#ifdef MODE_LIGHTSOURCE\n"
427 "varying vec3 CubeVector;\n"
428 "//#endif\n"
429 "\n"
430 "//#ifdef MODE_LIGHTSOURCE\n"
431 "varying vec3 LightVector;\n"
432 "//#else\n"
433 "//# ifdef MODE_LIGHTDIRECTION\n"
434 "//varying vec3 LightVector;\n"
435 "//# endif\n"
436 "//#endif\n"
437 "\n"
438 "varying vec3 EyeVector;\n"
439 "//#ifdef USEFOG\n"
440 "varying vec3 EyeVectorModelSpace;\n"
441 "//#endif\n"
442 "\n"
443 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
444 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
445 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
446 "\n"
447 "//#ifdef MODE_WATER\n"
448 "varying vec4 ModelViewProjectionPosition;\n"
449 "//#else\n"
450 "//# ifdef MODE_REFRACTION\n"
451 "//varying vec4 ModelViewProjectionPosition;\n"
452 "//# else\n"
453 "//#  ifdef USEREFLECTION\n"
454 "//varying vec4 ModelViewProjectionPosition;\n"
455 "//#  endif\n"
456 "//# endif\n"
457 "//#endif\n"
458 "\n"
459 "\n"
460 "\n"
461 "\n"
462 "\n"
463 "// vertex shader specific:\n"
464 "#ifdef VERTEX_SHADER\n"
465 "\n"
466 "uniform vec3 LightPosition;\n"
467 "uniform vec3 EyePosition;\n"
468 "uniform vec3 LightDir;\n"
469 "\n"
470 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
471 "\n"
472 "void main(void)\n"
473 "{\n"
474 "       gl_FrontColor = gl_Color;\n"
475 "       // copy the surface texcoord\n"
476 "       TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
477 "#ifndef MODE_LIGHTSOURCE\n"
478 "# ifndef MODE_LIGHTDIRECTION\n"
479 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
480 "# endif\n"
481 "#endif\n"
482 "\n"
483 "#ifdef MODE_LIGHTSOURCE\n"
484 "       // transform vertex position into light attenuation/cubemap space\n"
485 "       // (-1 to +1 across the light box)\n"
486 "       CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
487 "\n"
488 "       // transform unnormalized light direction into tangent space\n"
489 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
490 "       //  normalize it per pixel)\n"
491 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
492 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
493 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
494 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
495 "#endif\n"
496 "\n"
497 "#ifdef MODE_LIGHTDIRECTION\n"
498 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
499 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
500 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
501 "#endif\n"
502 "\n"
503 "       // transform unnormalized eye direction into tangent space\n"
504 "#ifndef USEFOG\n"
505 "       vec3 EyeVectorModelSpace;\n"
506 "#endif\n"
507 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
508 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
509 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
510 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
511 "\n"
512 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
513 "       VectorS = gl_MultiTexCoord1.xyz;\n"
514 "       VectorT = gl_MultiTexCoord2.xyz;\n"
515 "       VectorR = gl_MultiTexCoord3.xyz;\n"
516 "#endif\n"
517 "\n"
518 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
519 "//     ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
520 "//     //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
521 "//     //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
522 "//#endif\n"
523 "\n"
524 "// transform vertex to camera space, using ftransform to match non-VS\n"
525 "       // rendering\n"
526 "       gl_Position = ftransform();\n"
527 "\n"
528 "#ifdef MODE_WATER\n"
529 "       ModelViewProjectionPosition = gl_Position;\n"
530 "#endif\n"
531 "#ifdef MODE_REFRACTION\n"
532 "       ModelViewProjectionPosition = gl_Position;\n"
533 "#endif\n"
534 "#ifdef USEREFLECTION\n"
535 "       ModelViewProjectionPosition = gl_Position;\n"
536 "#endif\n"
537 "}\n"
538 "\n"
539 "#endif // VERTEX_SHADER\n"
540 "\n"
541 "\n"
542 "\n"
543 "\n"
544 "// fragment shader specific:\n"
545 "#ifdef FRAGMENT_SHADER\n"
546 "\n"
547 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
548 "uniform sampler2D Texture_Normal;\n"
549 "uniform sampler2D Texture_Color;\n"
550 "uniform sampler2D Texture_Gloss;\n"
551 "uniform samplerCube Texture_Cube;\n"
552 "uniform sampler2D Texture_Attenuation;\n"
553 "uniform sampler2D Texture_FogMask;\n"
554 "uniform sampler2D Texture_Pants;\n"
555 "uniform sampler2D Texture_Shirt;\n"
556 "uniform sampler2D Texture_Lightmap;\n"
557 "uniform sampler2D Texture_Deluxemap;\n"
558 "uniform sampler2D Texture_Glow;\n"
559 "uniform sampler2D Texture_Reflection;\n"
560 "uniform sampler2D Texture_Refraction;\n"
561 "\n"
562 "uniform myhvec3 LightColor;\n"
563 "uniform myhvec3 AmbientColor;\n"
564 "uniform myhvec3 DiffuseColor;\n"
565 "uniform myhvec3 SpecularColor;\n"
566 "uniform myhvec3 Color_Pants;\n"
567 "uniform myhvec3 Color_Shirt;\n"
568 "uniform myhvec3 FogColor;\n"
569 "\n"
570 "//#ifdef MODE_WATER\n"
571 "uniform vec4 DistortScaleRefractReflect;\n"
572 "uniform vec4 ScreenScaleRefractReflect;\n"
573 "uniform vec4 ScreenCenterRefractReflect;\n"
574 "uniform myhvec4 RefractColor;\n"
575 "uniform myhvec4 ReflectColor;\n"
576 "uniform myhalf ReflectFactor;\n"
577 "uniform myhalf ReflectOffset;\n"
578 "//#else\n"
579 "//# ifdef MODE_REFRACTION\n"
580 "//uniform vec4 DistortScaleRefractReflect;\n"
581 "//uniform vec4 ScreenScaleRefractReflect;\n"
582 "//uniform vec4 ScreenCenterRefractReflect;\n"
583 "//uniform myhvec4 RefractColor;\n"
584 "//#  ifdef USEREFLECTION\n"
585 "//uniform myhvec4 ReflectColor;\n"
586 "//#  endif\n"
587 "//# else\n"
588 "//#  ifdef USEREFLECTION\n"
589 "//uniform vec4 DistortScaleRefractReflect;\n"
590 "//uniform vec4 ScreenScaleRefractReflect;\n"
591 "//uniform vec4 ScreenCenterRefractReflect;\n"
592 "//uniform myhvec4 ReflectColor;\n"
593 "//#  endif\n"
594 "//# endif\n"
595 "//#endif\n"
596 "\n"
597 "uniform myhalf GlowScale;\n"
598 "uniform myhalf SceneBrightness;\n"
599 "#ifdef USECONTRASTBOOST\n"
600 "uniform myhalf ContrastBoostCoeff;\n"
601 "#endif\n"
602 "\n"
603 "uniform float OffsetMapping_Scale;\n"
604 "uniform float OffsetMapping_Bias;\n"
605 "uniform float FogRangeRecip;\n"
606 "\n"
607 "uniform myhalf AmbientScale;\n"
608 "uniform myhalf DiffuseScale;\n"
609 "uniform myhalf SpecularScale;\n"
610 "uniform myhalf SpecularPower;\n"
611 "\n"
612 "#ifdef USEOFFSETMAPPING\n"
613 "vec2 OffsetMapping(vec2 TexCoord)\n"
614 "{\n"
615 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
616 "       // 14 sample relief mapping: linear search and then binary search\n"
617 "       // this basically steps forward a small amount repeatedly until it finds\n"
618 "       // itself inside solid, then jitters forward and back using decreasing\n"
619 "       // amounts to find the impact\n"
620 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
621 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
622 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
623 "       vec3 RT = vec3(TexCoord, 1);\n"
624 "       OffsetVector *= 0.1;\n"
625 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
626 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
627 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
628 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
629 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
630 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
631 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
632 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
633 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
634 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
635 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
636 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
637 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
638 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
639 "       return RT.xy;\n"
640 "#else\n"
641 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
642 "       // this basically moves forward the full distance, and then backs up based\n"
643 "       // on height of samples\n"
644 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
645 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
646 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
647 "       TexCoord += OffsetVector;\n"
648 "       OffsetVector *= 0.333;\n"
649 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
650 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
651 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
652 "       return TexCoord;\n"
653 "#endif\n"
654 "}\n"
655 "#endif // USEOFFSETMAPPING\n"
656 "\n"
657 "#ifdef MODE_WATER\n"
658 "\n"
659 "// water pass\n"
660 "void main(void)\n"
661 "{\n"
662 "#ifdef USEOFFSETMAPPING\n"
663 "       // apply offsetmapping\n"
664 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
665 "#define TexCoord TexCoordOffset\n"
666 "#endif\n"
667 "\n"
668 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
669 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
670 "       vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
671 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
672 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
673 "}\n"
674 "\n"
675 "#else // MODE_WATER\n"
676 "#ifdef MODE_REFRACTION\n"
677 "\n"
678 "// refraction pass\n"
679 "void main(void)\n"
680 "{\n"
681 "#ifdef USEOFFSETMAPPING\n"
682 "       // apply offsetmapping\n"
683 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
684 "#define TexCoord TexCoordOffset\n"
685 "#endif\n"
686 "\n"
687 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
688 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
689 "       vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
690 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
691 "}\n"
692 "\n"
693 "#else // MODE_REFRACTION\n"
694 "void main(void)\n"
695 "{\n"
696 "#ifdef USEOFFSETMAPPING\n"
697 "       // apply offsetmapping\n"
698 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
699 "#define TexCoord TexCoordOffset\n"
700 "#endif\n"
701 "\n"
702 "       // combine the diffuse textures (base, pants, shirt)\n"
703 "       myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
704 "#ifdef USECOLORMAPPING\n"
705 "       color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
706 "#endif\n"
707 "\n"
708 "\n"
709 "\n"
710 "\n"
711 "#ifdef MODE_LIGHTSOURCE\n"
712 "       // light source\n"
713 "\n"
714 "       // calculate surface normal, light normal, and specular normal\n"
715 "       // compute color intensity for the two textures (colormap and glossmap)\n"
716 "       // scale by light color and attenuation as efficiently as possible\n"
717 "       // (do as much scalar math as possible rather than vector math)\n"
718 "# ifdef USESPECULAR\n"
719 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
720 "       myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
721 "       myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
722 "\n"
723 "       // calculate directional shading\n"
724 "       color.rgb = LightColor * 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)) * myhvec3(texture2D(Texture_Gloss, TexCoord)));\n"
725 "# else\n"
726 "#  ifdef USEDIFFUSE\n"
727 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
728 "       myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
729 "\n"
730 "       // calculate directional shading\n"
731 "       color.rgb = color.rgb * LightColor * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
732 "#  else\n"
733 "       // calculate directionless shading\n"
734 "       color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
735 "#  endif\n"
736 "# endif\n"
737 "\n"
738 "# ifdef USECUBEFILTER\n"
739 "       // apply light cubemap filter\n"
740 "       //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
741 "       color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
742 "# endif\n"
743 "       color *= myhvec4(gl_Color);\n"
744 "#endif // MODE_LIGHTSOURCE\n"
745 "\n"
746 "\n"
747 "\n"
748 "\n"
749 "#ifdef MODE_LIGHTDIRECTION\n"
750 "       // directional model lighting\n"
751 "# ifdef USESPECULAR\n"
752 "       // get the surface normal and light normal\n"
753 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
754 "       myhvec3 diffusenormal = myhvec3(LightVector);\n"
755 "\n"
756 "       // calculate directional shading\n"
757 "       color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
758 "       myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
759 "       color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
760 "# else\n"
761 "#  ifdef USEDIFFUSE\n"
762 "       // get the surface normal and light normal\n"
763 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
764 "       myhvec3 diffusenormal = myhvec3(LightVector);\n"
765 "\n"
766 "       // calculate directional shading\n"
767 "       color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
768 "#  else\n"
769 "       color.rgb *= AmbientColor;\n"
770 "#  endif\n"
771 "# endif\n"
772 "\n"
773 "       color *= myhvec4(gl_Color);\n"
774 "#endif // MODE_LIGHTDIRECTION\n"
775 "\n"
776 "\n"
777 "\n"
778 "\n"
779 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
780 "       // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
781 "\n"
782 "       // get the surface normal and light normal\n"
783 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
784 "\n"
785 "       myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
786 "       myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
787 "       // calculate directional shading\n"
788 "       myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
789 "# ifdef USESPECULAR\n"
790 "       myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
791 "       tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
792 "# endif\n"
793 "\n"
794 "       // apply lightmap color\n"
795 "       color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
796 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
797 "\n"
798 "\n"
799 "\n"
800 "\n"
801 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
802 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
803 "\n"
804 "       // get the surface normal and light normal\n"
805 "       myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
806 "\n"
807 "       myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
808 "       // calculate directional shading\n"
809 "       myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
810 "# ifdef USESPECULAR\n"
811 "       myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
812 "       tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
813 "# endif\n"
814 "\n"
815 "       // apply lightmap color\n"
816 "       color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
817 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
818 "\n"
819 "\n"
820 "\n"
821 "\n"
822 "#ifdef MODE_LIGHTMAP\n"
823 "       // apply lightmap color\n"
824 "       color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
825 "#endif // MODE_LIGHTMAP\n"
826 "\n"
827 "\n"
828 "\n"
829 "\n"
830 "\n"
831 "\n"
832 "\n"
833 "\n"
834 "#ifdef USEGLOW\n"
835 "       color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
836 "#endif\n"
837 "\n"
838 "#ifndef MODE_LIGHTSOURCE\n"
839 "# ifdef USEREFLECTION\n"
840 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
841 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
842 "       vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
843 "       color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
844 "# endif\n"
845 "#endif\n"
846 "\n"
847 "#ifdef USEFOG\n"
848 "       // apply fog\n"
849 "       color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
850 "#endif\n"
851 "\n"
852 "#ifdef USECONTRASTBOOST\n"
853 "       color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
854 "#endif\n"
855 "\n"
856 "       color.rgb *= SceneBrightness;\n"
857 "\n"
858 "       gl_FragColor = vec4(color);\n"
859 "}\n"
860 "#endif // MODE_REFRACTION\n"
861 "#endif // MODE_WATER\n"
862 "\n"
863 "#endif // FRAGMENT_SHADER\n"
864 ;
865
866 #define SHADERPERMUTATION_COLORMAPPING (1<<0) // indicates this is a colormapped skin
867 #define SHADERPERMUTATION_CONTRASTBOOST (1<<1) // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
868 #define SHADERPERMUTATION_FOG (1<<2) // tint the color by fog color or black if using additive blend mode
869 #define SHADERPERMUTATION_CUBEFILTER (1<<3) // (lightsource) use cubemap light filter
870 #define SHADERPERMUTATION_GLOW (1<<4) // (lightmap) blend in an additive glow texture
871 #define SHADERPERMUTATION_DIFFUSE (1<<5) // (lightsource) whether to use directional shading
872 #define SHADERPERMUTATION_SPECULAR (1<<6) // (lightsource or deluxemapping) render specular effects
873 #define SHADERPERMUTATION_REFLECTION (1<<7) // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
874 #define SHADERPERMUTATION_OFFSETMAPPING (1<<8) // adjust texcoords to roughly simulate a displacement mapped surface
875 #define SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING (1<<9) // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
876 #define SHADERPERMUTATION_MODEBASE (1<<10) // multiplier for the SHADERMODE_ values to get a valid index
877
878 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
879 const char *shaderpermutationinfo[][2] =
880 {
881         {"#define USECOLORMAPPING\n", " colormapping"},
882         {"#define USECONTRASTBOOST\n", " contrastboost"},
883         {"#define USEFOG\n", " fog"},
884         {"#define USECUBEFILTER\n", " cubefilter"},
885         {"#define USEGLOW\n", " glow"},
886         {"#define USEDIFFUSE\n", " diffuse"},
887         {"#define USESPECULAR\n", " specular"},
888         {"#define USEREFLECTION\n", " reflection"},
889         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
890         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
891         {NULL, NULL}
892 };
893
894 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
895 typedef enum shadermode_e
896 {
897         SHADERMODE_LIGHTMAP, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
898         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (deluxemap)
899         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (deluxemap)
900         SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
901         SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
902         SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
903         SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
904         SHADERMODE_COUNT
905 }
906 shadermode_t;
907
908 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
909 const char *shadermodeinfo[][2] =
910 {
911         {"#define MODE_LIGHTMAP\n", " lightmap"},
912         {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
913         {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
914         {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
915         {"#define MODE_LIGHTSOURCE\n", " lightsource"},
916         {"#define MODE_REFRACTION\n", " refraction"},
917         {"#define MODE_WATER\n", " water"},
918         {NULL, NULL}
919 };
920
921 #define SHADERPERMUTATION_INDICES (SHADERPERMUTATION_MODEBASE * SHADERMODE_COUNT)
922
923 typedef struct r_glsl_permutation_s
924 {
925         // indicates if we have tried compiling this permutation already
926         qboolean compiled;
927         // 0 if compilation failed
928         int program;
929         // locations of detected uniforms in program object, or -1 if not found
930         int loc_Texture_Normal;
931         int loc_Texture_Color;
932         int loc_Texture_Gloss;
933         int loc_Texture_Cube;
934         int loc_Texture_Attenuation;
935         int loc_Texture_FogMask;
936         int loc_Texture_Pants;
937         int loc_Texture_Shirt;
938         int loc_Texture_Lightmap;
939         int loc_Texture_Deluxemap;
940         int loc_Texture_Glow;
941         int loc_Texture_Refraction;
942         int loc_Texture_Reflection;
943         int loc_FogColor;
944         int loc_LightPosition;
945         int loc_EyePosition;
946         int loc_LightColor;
947         int loc_Color_Pants;
948         int loc_Color_Shirt;
949         int loc_FogRangeRecip;
950         int loc_AmbientScale;
951         int loc_DiffuseScale;
952         int loc_SpecularScale;
953         int loc_SpecularPower;
954         int loc_GlowScale;
955         int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
956         int loc_OffsetMapping_Scale;
957         int loc_AmbientColor;
958         int loc_DiffuseColor;
959         int loc_SpecularColor;
960         int loc_LightDir;
961         int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
962         int loc_DistortScaleRefractReflect;
963         int loc_ScreenScaleRefractReflect;
964         int loc_ScreenCenterRefractReflect;
965         int loc_RefractColor;
966         int loc_ReflectColor;
967         int loc_ReflectFactor;
968         int loc_ReflectOffset;
969 }
970 r_glsl_permutation_t;
971
972 // information about each possible shader permutation
973 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_INDICES];
974 // currently selected permutation
975 r_glsl_permutation_t *r_glsl_permutation;
976
977 // these are additional flags used only by R_GLSL_CompilePermutation
978 #define SHADERTYPE_USES_VERTEXSHADER (1<<0)
979 #define SHADERTYPE_USES_GEOMETRYSHADER (1<<1)
980 #define SHADERTYPE_USES_FRAGMENTSHADER (1<<2)
981
982 static void R_GLSL_CompilePermutation(const char *filename, int permutation, int shadertype)
983 {
984         int i;
985         qboolean shaderfound;
986         r_glsl_permutation_t *p = r_glsl_permutations + permutation;
987         int vertstrings_count;
988         int geomstrings_count;
989         int fragstrings_count;
990         char *shaderstring;
991         const char *vertstrings_list[32+1];
992         const char *geomstrings_list[32+1];
993         const char *fragstrings_list[32+1];
994         char permutationname[256];
995         if (p->compiled)
996                 return;
997         p->compiled = true;
998         p->program = 0;
999         vertstrings_list[0] = "#define VERTEX_SHADER\n";
1000         geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
1001         fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
1002         vertstrings_count = 1;
1003         geomstrings_count = 1;
1004         fragstrings_count = 1;
1005         permutationname[0] = 0;
1006         i = permutation / SHADERPERMUTATION_MODEBASE;
1007         vertstrings_list[vertstrings_count++] = shadermodeinfo[i][0];
1008         geomstrings_list[geomstrings_count++] = shadermodeinfo[i][0];
1009         fragstrings_list[fragstrings_count++] = shadermodeinfo[i][0];
1010         strlcat(permutationname, shadermodeinfo[i][1], sizeof(permutationname));
1011         for (i = 0;shaderpermutationinfo[i][0];i++)
1012         {
1013                 if (permutation & (1<<i))
1014                 {
1015                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i][0];
1016                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i][0];
1017                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i][0];
1018                         strlcat(permutationname, shaderpermutationinfo[i][1], sizeof(permutationname));
1019                 }
1020                 else
1021                 {
1022                         // keep line numbers correct
1023                         vertstrings_list[vertstrings_count++] = "\n";
1024                         geomstrings_list[geomstrings_count++] = "\n";
1025                         fragstrings_list[fragstrings_count++] = "\n";
1026                 }
1027         }
1028         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1029         shaderfound = false;
1030         if (shaderstring)
1031         {
1032                 Con_DPrint("from disk... ");
1033                 vertstrings_list[vertstrings_count++] = shaderstring;
1034                 geomstrings_list[geomstrings_count++] = shaderstring;
1035                 fragstrings_list[fragstrings_count++] = shaderstring;
1036                 shaderfound = true;
1037         }
1038         else if (!strcmp(filename, "glsl/default.glsl"))
1039         {
1040                 vertstrings_list[vertstrings_count++] = builtinshaderstring;
1041                 geomstrings_list[geomstrings_count++] = builtinshaderstring;
1042                 fragstrings_list[fragstrings_count++] = builtinshaderstring;
1043                 shaderfound = true;
1044         }
1045         // clear any lists that are not needed by this shader
1046         if (!(shadertype & SHADERTYPE_USES_VERTEXSHADER))
1047                 vertstrings_count = 0;
1048         if (!(shadertype & SHADERTYPE_USES_GEOMETRYSHADER))
1049                 geomstrings_count = 0;
1050         if (!(shadertype & SHADERTYPE_USES_FRAGMENTSHADER))
1051                 fragstrings_count = 0;
1052         // compile the shader program
1053         if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
1054                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1055         if (p->program)
1056         {
1057                 CHECKGLERROR
1058                 qglUseProgramObjectARB(p->program);CHECKGLERROR
1059                 // look up all the uniform variable names we care about, so we don't
1060                 // have to look them up every time we set them
1061                 p->loc_Texture_Normal      = qglGetUniformLocationARB(p->program, "Texture_Normal");
1062                 p->loc_Texture_Color       = qglGetUniformLocationARB(p->program, "Texture_Color");
1063                 p->loc_Texture_Gloss       = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1064                 p->loc_Texture_Cube        = qglGetUniformLocationARB(p->program, "Texture_Cube");
1065                 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1066                 p->loc_Texture_FogMask     = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1067                 p->loc_Texture_Pants       = qglGetUniformLocationARB(p->program, "Texture_Pants");
1068                 p->loc_Texture_Shirt       = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1069                 p->loc_Texture_Lightmap    = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1070                 p->loc_Texture_Deluxemap   = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1071                 p->loc_Texture_Glow        = qglGetUniformLocationARB(p->program, "Texture_Glow");
1072                 p->loc_Texture_Refraction  = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1073                 p->loc_Texture_Reflection  = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1074                 p->loc_FogColor            = qglGetUniformLocationARB(p->program, "FogColor");
1075                 p->loc_LightPosition       = qglGetUniformLocationARB(p->program, "LightPosition");
1076                 p->loc_EyePosition         = qglGetUniformLocationARB(p->program, "EyePosition");
1077                 p->loc_LightColor          = qglGetUniformLocationARB(p->program, "LightColor");
1078                 p->loc_Color_Pants         = qglGetUniformLocationARB(p->program, "Color_Pants");
1079                 p->loc_Color_Shirt         = qglGetUniformLocationARB(p->program, "Color_Shirt");
1080                 p->loc_FogRangeRecip       = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1081                 p->loc_AmbientScale        = qglGetUniformLocationARB(p->program, "AmbientScale");
1082                 p->loc_DiffuseScale        = qglGetUniformLocationARB(p->program, "DiffuseScale");
1083                 p->loc_SpecularPower       = qglGetUniformLocationARB(p->program, "SpecularPower");
1084                 p->loc_SpecularScale       = qglGetUniformLocationARB(p->program, "SpecularScale");
1085                 p->loc_GlowScale           = qglGetUniformLocationARB(p->program, "GlowScale");
1086                 p->loc_SceneBrightness     = qglGetUniformLocationARB(p->program, "SceneBrightness");
1087                 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1088                 p->loc_AmbientColor        = qglGetUniformLocationARB(p->program, "AmbientColor");
1089                 p->loc_DiffuseColor        = qglGetUniformLocationARB(p->program, "DiffuseColor");
1090                 p->loc_SpecularColor       = qglGetUniformLocationARB(p->program, "SpecularColor");
1091                 p->loc_LightDir            = qglGetUniformLocationARB(p->program, "LightDir");
1092                 p->loc_ContrastBoostCoeff  = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1093                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1094                 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1095                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1096                 p->loc_RefractColor        = qglGetUniformLocationARB(p->program, "RefractColor");
1097                 p->loc_ReflectColor        = qglGetUniformLocationARB(p->program, "ReflectColor");
1098                 p->loc_ReflectFactor       = qglGetUniformLocationARB(p->program, "ReflectFactor");
1099                 p->loc_ReflectOffset       = qglGetUniformLocationARB(p->program, "ReflectOffset");
1100                 // initialize the samplers to refer to the texture units we use
1101                 if (p->loc_Texture_Normal >= 0)    qglUniform1iARB(p->loc_Texture_Normal, 0);
1102                 if (p->loc_Texture_Color >= 0)     qglUniform1iARB(p->loc_Texture_Color, 1);
1103                 if (p->loc_Texture_Gloss >= 0)     qglUniform1iARB(p->loc_Texture_Gloss, 2);
1104                 if (p->loc_Texture_Cube >= 0)      qglUniform1iARB(p->loc_Texture_Cube, 3);
1105                 if (p->loc_Texture_FogMask >= 0)   qglUniform1iARB(p->loc_Texture_FogMask, 4);
1106                 if (p->loc_Texture_Pants >= 0)     qglUniform1iARB(p->loc_Texture_Pants, 5);
1107                 if (p->loc_Texture_Shirt >= 0)     qglUniform1iARB(p->loc_Texture_Shirt, 6);
1108                 if (p->loc_Texture_Lightmap >= 0)  qglUniform1iARB(p->loc_Texture_Lightmap, 7);
1109                 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
1110                 if (p->loc_Texture_Glow >= 0)      qglUniform1iARB(p->loc_Texture_Glow, 9);
1111                 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
1112                 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
1113                 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
1114                 CHECKGLERROR
1115                 qglUseProgramObjectARB(0);CHECKGLERROR
1116                 if (developer.integer)
1117                         Con_Printf("GLSL shader %s :%s compiled.\n", filename, permutationname);
1118         }
1119         else
1120         {
1121                 if (developer.integer)
1122                         Con_Printf("GLSL shader %s :%s failed!  source code line offset for above errors is %i.\n", permutationname, filename, -(vertstrings_count - 1));
1123                 else
1124                         Con_Printf("GLSL shader %s :%s failed!  some features may not work properly.\n", permutationname, filename);
1125         }
1126         if (shaderstring)
1127                 Mem_Free(shaderstring);
1128 }
1129
1130 void R_GLSL_Restart_f(void)
1131 {
1132         int i;
1133         for (i = 0;i < SHADERPERMUTATION_INDICES;i++)
1134                 if (r_glsl_permutations[i].program)
1135                         GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1136         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1137 }
1138
1139 void R_GLSL_DumpShader_f(void)
1140 {
1141         int i;
1142
1143         qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1144         if(!file)
1145         {
1146                 Con_Printf("failed to write to glsl/default.glsl\n");
1147                 return;
1148         }
1149
1150         FS_Print(file, "// The engine may define the following macros:\n");
1151         FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1152         for (i = 0;shadermodeinfo[i][0];i++)
1153                 FS_Printf(file, "// %s", shadermodeinfo[i][0]);
1154         for (i = 0;shaderpermutationinfo[i][0];i++)
1155                 FS_Printf(file, "// %s", shaderpermutationinfo[i][0]);
1156         FS_Print(file, "\n");
1157         FS_Print(file, builtinshaderstring);
1158         FS_Close(file);
1159
1160         Con_Printf("glsl/default.glsl written\n");
1161 }
1162
1163 extern rtexture_t *r_shadow_attenuationgradienttexture;
1164 extern rtexture_t *r_shadow_attenuation2dtexture;
1165 extern rtexture_t *r_shadow_attenuation3dtexture;
1166 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1167 {
1168         // select a permutation of the lighting shader appropriate to this
1169         // combination of texture, entity, light source, and fogging, only use the
1170         // minimum features necessary to avoid wasting rendering time in the
1171         // fragment shader on features that are not being used
1172         const char *shaderfilename = NULL;
1173         unsigned int permutation = 0;
1174         unsigned int shadertype = 0;
1175         shadermode_t mode = 0;
1176         r_glsl_permutation = NULL;
1177         shaderfilename = "glsl/default.glsl";
1178         shadertype = SHADERTYPE_USES_VERTEXSHADER | SHADERTYPE_USES_FRAGMENTSHADER;
1179         // TODO: implement geometry-shader based shadow volumes someday
1180         if (r_glsl_offsetmapping.integer)
1181         {
1182                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1183                 if (r_glsl_offsetmapping_reliefmapping.integer)
1184                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1185         }
1186         if (rsurfacepass == RSURFPASS_BACKGROUND)
1187         {
1188                 // distorted background
1189                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1190                         mode = SHADERMODE_WATER;
1191                 else
1192                         mode = SHADERMODE_REFRACTION;
1193         }
1194         else if (rsurfacepass == RSURFPASS_RTLIGHT)
1195         {
1196                 // light source
1197                 mode = SHADERMODE_LIGHTSOURCE;
1198                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1199                         permutation |= SHADERPERMUTATION_CUBEFILTER;
1200                 if (diffusescale > 0)
1201                         permutation |= SHADERPERMUTATION_DIFFUSE;
1202                 if (specularscale > 0)
1203                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1204                 if (r_refdef.fogenabled)
1205                         permutation |= SHADERPERMUTATION_FOG;
1206                 if (rsurface.texture->colormapping)
1207                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1208                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1209                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1210                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1211                         permutation |= SHADERPERMUTATION_REFLECTION;
1212         }
1213         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1214         {
1215                 // unshaded geometry (fullbright or ambient model lighting)
1216                 mode = SHADERMODE_LIGHTMAP;
1217                 if (rsurface.texture->currentskinframe->glow)
1218                         permutation |= SHADERPERMUTATION_GLOW;
1219                 if (r_refdef.fogenabled)
1220                         permutation |= SHADERPERMUTATION_FOG;
1221                 if (rsurface.texture->colormapping)
1222                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1223                 if (r_glsl_offsetmapping.integer)
1224                 {
1225                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1226                         if (r_glsl_offsetmapping_reliefmapping.integer)
1227                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1228                 }
1229                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1230                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1231                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1232                         permutation |= SHADERPERMUTATION_REFLECTION;
1233         }
1234         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1235         {
1236                 // directional model lighting
1237                 mode = SHADERMODE_LIGHTDIRECTION;
1238                 if (rsurface.texture->currentskinframe->glow)
1239                         permutation |= SHADERPERMUTATION_GLOW;
1240                 permutation |= SHADERPERMUTATION_DIFFUSE;
1241                 if (specularscale > 0)
1242                         permutation |= SHADERPERMUTATION_SPECULAR;
1243                 if (r_refdef.fogenabled)
1244                         permutation |= SHADERPERMUTATION_FOG;
1245                 if (rsurface.texture->colormapping)
1246                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1247                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1248                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1249                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1250                         permutation |= SHADERPERMUTATION_REFLECTION;
1251         }
1252         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1253         {
1254                 // ambient model lighting
1255                 mode = SHADERMODE_LIGHTDIRECTION;
1256                 if (rsurface.texture->currentskinframe->glow)
1257                         permutation |= SHADERPERMUTATION_GLOW;
1258                 if (r_refdef.fogenabled)
1259                         permutation |= SHADERPERMUTATION_FOG;
1260                 if (rsurface.texture->colormapping)
1261                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1262                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1263                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1264                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1265                         permutation |= SHADERPERMUTATION_REFLECTION;
1266         }
1267         else
1268         {
1269                 // lightmapped wall
1270                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1271                 {
1272                         // deluxemapping (light direction texture)
1273                         if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1274                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1275                         else
1276                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1277                         if (specularscale > 0)
1278                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1279                 }
1280                 else if (r_glsl_deluxemapping.integer >= 2)
1281                 {
1282                         // fake deluxemapping (uniform light direction in tangentspace)
1283                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1284                         if (specularscale > 0)
1285                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1286                 }
1287                 else
1288                 {
1289                         // ordinary lightmapping
1290                         mode = SHADERMODE_LIGHTMAP;
1291                 }
1292                 if (rsurface.texture->currentskinframe->glow)
1293                         permutation |= SHADERPERMUTATION_GLOW;
1294                 if (r_refdef.fogenabled)
1295                         permutation |= SHADERPERMUTATION_FOG;
1296                 if (rsurface.texture->colormapping)
1297                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1298                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1299                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1300                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1301                         permutation |= SHADERPERMUTATION_REFLECTION;
1302         }
1303         permutation |= mode * SHADERPERMUTATION_MODEBASE;
1304         if (!r_glsl_permutations[permutation].program)
1305         {
1306                 if (!r_glsl_permutations[permutation].compiled)
1307                         R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1308                 if (!r_glsl_permutations[permutation].program)
1309                 {
1310                         // remove features until we find a valid permutation
1311                         unsigned int i;
1312                         for (i = (SHADERPERMUTATION_MODEBASE >> 1);;i>>=1)
1313                         {
1314                                 if (!i)
1315                                 {
1316                                         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");
1317                                         Cvar_SetValueQuick(&r_glsl, 0);
1318                                         return 0; // no bit left to clear
1319                                 }
1320                                 // reduce i more quickly whenever it would not remove any bits
1321                                 if (!(permutation & i))
1322                                         continue;
1323                                 permutation &= ~i;
1324                                 if (!r_glsl_permutations[permutation].compiled)
1325                                         R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1326                                 if (r_glsl_permutations[permutation].program)
1327                                         break;
1328                         }
1329                 }
1330         }
1331         r_glsl_permutation = r_glsl_permutations + permutation;
1332         CHECKGLERROR
1333         qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1334         if (mode == SHADERMODE_LIGHTSOURCE)
1335         {
1336                 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1337                 if (permutation & SHADERPERMUTATION_DIFFUSE)
1338                 {
1339                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1340                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1341                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1342                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1343                 }
1344                 else
1345                 {
1346                         // ambient only is simpler
1347                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1348                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1349                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1350                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1351                 }
1352         }
1353         else if (mode == SHADERMODE_LIGHTDIRECTION)
1354         {
1355                 if (r_glsl_permutation->loc_AmbientColor >= 0)
1356                         qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1357                 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1358                         qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1359                 if (r_glsl_permutation->loc_SpecularColor >= 0)
1360                         qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1361                 if (r_glsl_permutation->loc_LightDir >= 0)
1362                         qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1363         }
1364         else
1365         {
1366                 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1367                 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1368                 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1369         }
1370         if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1371         if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1372         {
1373                 // The formula used is actually:
1374                 //   color.rgb *= SceneBrightness;
1375                 //   color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1376                 // I simplify that to
1377                 //   color.rgb *= [[SceneBrightness * ContrastBoost]];
1378                 //   color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1379                 // and Black:
1380                 //   color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[(ContrastBoost - 1) * SceneBrightness]] * color.rgb + 1);
1381                 // and do [[calculations]] here in the engine
1382                 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1383                 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1384         }
1385         else
1386                 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1387         if (r_glsl_permutation->loc_FogColor >= 0)
1388         {
1389                 // additive passes are only darkened by fog, not tinted
1390                 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1391                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1392                 else
1393                 /*
1394                 {
1395                         vec3_t fogvec;
1396                         //   color.rgb *= SceneBrightness;
1397                         VectorScale(r_refdef.fogcolor, r_view.colorscale, fogvec);
1398                         if(r_glsl_permutation->loc_ContrastBoostCoeff >= 0) // need to support contrast boost
1399                         {
1400                                 //   color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1401                                 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
1402                                 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
1403                                 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
1404                         }
1405                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogvec[0], fogvec[1], fogvec[2]);
1406                 }
1407                 */
1408                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1409         }
1410         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1411         if (r_glsl_permutation->loc_Color_Pants >= 0)
1412         {
1413                 if (rsurface.texture->currentskinframe->pants)
1414                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1415                 else
1416                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1417         }
1418         if (r_glsl_permutation->loc_Color_Shirt >= 0)
1419         {
1420                 if (rsurface.texture->currentskinframe->shirt)
1421                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1422                 else
1423                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1424         }
1425         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1426         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1427         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1428         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);
1429         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]);
1430         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]);
1431         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1432         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1433         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1434         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1435         CHECKGLERROR
1436         return permutation;
1437 }
1438
1439 #define SKINFRAME_HASH 1024
1440
1441 struct
1442 {
1443         int loadsequence; // incremented each level change
1444         memexpandablearray_t array;
1445         skinframe_t *hash[SKINFRAME_HASH];
1446 }
1447 r_skinframe;
1448
1449 void R_SkinFrame_PrepareForPurge(void)
1450 {
1451         r_skinframe.loadsequence++;
1452         // wrap it without hitting zero
1453         if (r_skinframe.loadsequence >= 200)
1454                 r_skinframe.loadsequence = 1;
1455 }
1456
1457 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1458 {
1459         if (!skinframe)
1460                 return;
1461         // mark the skinframe as used for the purging code
1462         skinframe->loadsequence = r_skinframe.loadsequence;
1463 }
1464
1465 void R_SkinFrame_Purge(void)
1466 {
1467         int i;
1468         skinframe_t *s;
1469         for (i = 0;i < SKINFRAME_HASH;i++)
1470         {
1471                 for (s = r_skinframe.hash[i];s;s = s->next)
1472                 {
1473                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1474                         {
1475                                 if (s->base == r_texture_notexture)     s->base   = NULL;
1476                                 if (s->nmap == r_texture_blanknormalmap)s->nmap   = NULL;
1477                                 if (s->merged == s->base)               s->merged = NULL;
1478                                 if (s->stain ) R_FreeTexture(s->stain );s->stain  = NULL;
1479                                 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1480                                 if (s->base  ) R_FreeTexture(s->base  );s->base   = NULL;
1481                                 if (s->pants ) R_FreeTexture(s->pants );s->pants  = NULL;
1482                                 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt  = NULL;
1483                                 if (s->nmap  ) R_FreeTexture(s->nmap  );s->nmap   = NULL;
1484                                 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss  = NULL;
1485                                 if (s->glow  ) R_FreeTexture(s->glow  );s->glow   = NULL;
1486                                 if (s->fog   ) R_FreeTexture(s->fog   );s->fog    = NULL;
1487                                 s->loadsequence = 0;
1488                         }
1489                 }
1490         }
1491 }
1492
1493 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1494         skinframe_t *item;
1495         char basename[MAX_QPATH];
1496
1497         Image_StripImageExtension(name, basename, sizeof(basename));
1498
1499         if( last == NULL ) {
1500                 int hashindex;
1501                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1502                 item = r_skinframe.hash[hashindex];
1503         } else {
1504                 item = last->next;
1505         }
1506
1507         // linearly search through the hash bucket
1508         for( ; item ; item = item->next ) {
1509                 if( !strcmp( item->basename, basename ) ) {
1510                         return item;
1511                 }
1512         }
1513         return NULL;
1514 }
1515
1516 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1517 {
1518         skinframe_t *item;
1519         int hashindex;
1520         char basename[MAX_QPATH];
1521
1522         Image_StripImageExtension(name, basename, sizeof(basename));
1523
1524         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1525         for (item = r_skinframe.hash[hashindex];item;item = item->next)
1526                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1527                         break;
1528         if (!item)
1529         {
1530                 rtexture_t *dyntexture;
1531                 // check whether its a dynamic texture
1532                 dyntexture = CL_GetDynTexture( basename );
1533                 if (!add && !dyntexture)
1534                         return NULL;
1535                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1536                 memset(item, 0, sizeof(*item));
1537                 strlcpy(item->basename, basename, sizeof(item->basename));
1538                 item->textureflags = textureflags;
1539                 item->base = dyntexture;
1540                 item->comparewidth = comparewidth;
1541                 item->compareheight = compareheight;
1542                 item->comparecrc = comparecrc;
1543                 item->next = r_skinframe.hash[hashindex];       
1544                 r_skinframe.hash[hashindex] = item;
1545         }
1546         R_SkinFrame_MarkUsed(item);
1547         return item;
1548 }
1549
1550 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1551 {
1552         // FIXME: it should be possible to disable loading various layers using
1553         // cvars, to prevent wasted loading time and memory usage if the user does
1554         // not want them
1555         qboolean loadnormalmap = true;
1556         qboolean loadgloss = true;
1557         qboolean loadpantsandshirt = true;
1558         qboolean loadglow = true;
1559         int j;
1560         unsigned char *pixels;
1561         unsigned char *bumppixels;
1562         unsigned char *basepixels = NULL;
1563         int basepixels_width;
1564         int basepixels_height;
1565         skinframe_t *skinframe;
1566
1567         if (cls.state == ca_dedicated)
1568                 return NULL;
1569
1570         // return an existing skinframe if already loaded
1571         // if loading of the first image fails, don't make a new skinframe as it
1572         // would cause all future lookups of this to be missing
1573         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1574         if (skinframe && skinframe->base)
1575                 return skinframe;
1576
1577         basepixels = loadimagepixelsbgra(name, complain, true);
1578         if (basepixels == NULL)
1579                 return NULL;
1580
1581         // we've got some pixels to store, so really allocate this new texture now
1582         if (!skinframe)
1583                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1584         skinframe->stain = NULL;
1585         skinframe->merged = NULL;
1586         skinframe->base = r_texture_notexture;
1587         skinframe->pants = NULL;
1588         skinframe->shirt = NULL;
1589         skinframe->nmap = r_texture_blanknormalmap;
1590         skinframe->gloss = NULL;
1591         skinframe->glow = NULL;
1592         skinframe->fog = NULL;
1593
1594         basepixels_width = image_width;
1595         basepixels_height = image_height;
1596         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);
1597
1598         if (textureflags & TEXF_ALPHA)
1599         {
1600                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1601                         if (basepixels[j] < 255)
1602                                 break;
1603                 if (j < basepixels_width * basepixels_height * 4)
1604                 {
1605                         // has transparent pixels
1606                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1607                         for (j = 0;j < image_width * image_height * 4;j += 4)
1608                         {
1609                                 pixels[j+0] = 255;
1610                                 pixels[j+1] = 255;
1611                                 pixels[j+2] = 255;
1612                                 pixels[j+3] = basepixels[j+3];
1613                         }
1614                         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);
1615                         Mem_Free(pixels);
1616                 }
1617         }
1618
1619         // _norm is the name used by tenebrae and has been adopted as standard
1620         if (loadnormalmap)
1621         {
1622                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1623                 {
1624                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1625                         Mem_Free(pixels);
1626                         pixels = NULL;
1627                 }
1628                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1629                 {
1630                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1631                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1632                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1633                         Mem_Free(pixels);
1634                         Mem_Free(bumppixels);
1635                 }
1636                 else if (r_shadow_bumpscale_basetexture.value > 0)
1637                 {
1638                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1639                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1640                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1641                         Mem_Free(pixels);
1642                 }
1643         }
1644         // _luma is supported for tenebrae compatibility
1645         // (I think it's a very stupid name, but oh well)
1646         // _glow is the preferred name
1647         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;}
1648         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;}
1649         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;}
1650         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;}
1651
1652         if (basepixels)
1653                 Mem_Free(basepixels);
1654
1655         return skinframe;
1656 }
1657
1658 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)
1659 {
1660         int i;
1661         if (!force)
1662         {
1663                 for (i = 0;i < width*height;i++)
1664                         if (((unsigned char *)&palette[in[i]])[3] > 0)
1665                                 break;
1666                 if (i == width*height)
1667                         return NULL;
1668         }
1669         return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1670 }
1671
1672 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1673 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1674 {
1675         int i;
1676         unsigned char *temp1, *temp2;
1677         skinframe_t *skinframe;
1678
1679         if (cls.state == ca_dedicated)
1680                 return NULL;
1681
1682         // if already loaded just return it, otherwise make a new skinframe
1683         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
1684         if (skinframe && skinframe->base)
1685                 return skinframe;
1686
1687         skinframe->stain = NULL;
1688         skinframe->merged = NULL;
1689         skinframe->base = r_texture_notexture;
1690         skinframe->pants = NULL;
1691         skinframe->shirt = NULL;
1692         skinframe->nmap = r_texture_blanknormalmap;
1693         skinframe->gloss = NULL;
1694         skinframe->glow = NULL;
1695         skinframe->fog = NULL;
1696
1697         // if no data was provided, then clearly the caller wanted to get a blank skinframe
1698         if (!skindata)
1699                 return NULL;
1700
1701         if (r_shadow_bumpscale_basetexture.value > 0)
1702         {
1703                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1704                 temp2 = temp1 + width * height * 4;
1705                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1706                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1707                 Mem_Free(temp1);
1708         }
1709         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1710         if (textureflags & TEXF_ALPHA)
1711         {
1712                 for (i = 3;i < width * height * 4;i += 4)
1713                         if (skindata[i] < 255)
1714                                 break;
1715                 if (i < width * height * 4)
1716                 {
1717                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1718                         memcpy(fogpixels, skindata, width * height * 4);
1719                         for (i = 0;i < width * height * 4;i += 4)
1720                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1721                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1722                         Mem_Free(fogpixels);
1723                 }
1724         }
1725
1726         return skinframe;
1727 }
1728
1729 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
1730 {
1731         int i;
1732         unsigned char *temp1, *temp2;
1733         skinframe_t *skinframe;
1734
1735         if (cls.state == ca_dedicated)
1736                 return NULL;
1737
1738         // if already loaded just return it, otherwise make a new skinframe
1739         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
1740         if (skinframe && skinframe->base)
1741                 return skinframe;
1742
1743         skinframe->stain = NULL;
1744         skinframe->merged = NULL;
1745         skinframe->base = r_texture_notexture;
1746         skinframe->pants = NULL;
1747         skinframe->shirt = NULL;
1748         skinframe->nmap = r_texture_blanknormalmap;
1749         skinframe->gloss = NULL;
1750         skinframe->glow = NULL;
1751         skinframe->fog = NULL;
1752
1753         // if no data was provided, then clearly the caller wanted to get a blank skinframe
1754         if (!skindata)
1755                 return NULL;
1756
1757         if (r_shadow_bumpscale_basetexture.value > 0)
1758         {
1759                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1760                 temp2 = temp1 + width * height * 4;
1761                 // use either a custom palette or the quake palette
1762                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
1763                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1764                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1765                 Mem_Free(temp1);
1766         }
1767         // use either a custom palette, or the quake palette
1768         skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete)), skinframe->textureflags, true); // all
1769         if (loadglowtexture)
1770                 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
1771         if (loadpantsandshirt)
1772         {
1773                 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
1774                 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
1775         }
1776         if (skinframe->pants || skinframe->shirt)
1777                 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
1778         if (textureflags & TEXF_ALPHA)
1779         {
1780                 for (i = 0;i < width * height;i++)
1781                         if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
1782                                 break;
1783                 if (i < width * height)
1784                         skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
1785         }
1786
1787         return skinframe;
1788 }
1789
1790 skinframe_t *R_SkinFrame_LoadMissing(void)
1791 {
1792         skinframe_t *skinframe;
1793
1794         if (cls.state == ca_dedicated)
1795                 return NULL;
1796
1797         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1798         skinframe->stain = NULL;
1799         skinframe->merged = NULL;
1800         skinframe->base = r_texture_notexture;
1801         skinframe->pants = NULL;
1802         skinframe->shirt = NULL;
1803         skinframe->nmap = r_texture_blanknormalmap;
1804         skinframe->gloss = NULL;
1805         skinframe->glow = NULL;
1806         skinframe->fog = NULL;
1807
1808         return skinframe;
1809 }
1810
1811 void gl_main_start(void)
1812 {
1813         int x;
1814         double r, alpha;
1815
1816         r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1817         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1818         {
1819                 alpha = 1 - exp(r / ((double)x*(double)x));
1820                 if (x == FOGMASKTABLEWIDTH - 1)
1821                         alpha = 0;
1822                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1823         }
1824
1825         memset(r_qwskincache, 0, sizeof(r_qwskincache));
1826         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1827
1828         // set up r_skinframe loading system for textures
1829         memset(&r_skinframe, 0, sizeof(r_skinframe));
1830         r_skinframe.loadsequence = 1;
1831         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1832
1833         r_main_texturepool = R_AllocTexturePool();
1834         R_BuildBlankTextures();
1835         R_BuildNoTexture();
1836         if (gl_texturecubemap)
1837         {
1838                 R_BuildWhiteCube();
1839                 R_BuildNormalizationCube();
1840         }
1841         R_BuildFogTexture();
1842         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1843         memset(&r_waterstate, 0, sizeof(r_waterstate));
1844         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1845         memset(&r_svbsp, 0, sizeof (r_svbsp));
1846 }
1847
1848 void gl_main_shutdown(void)
1849 {
1850         memset(r_qwskincache, 0, sizeof(r_qwskincache));
1851         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1852
1853         // clear out the r_skinframe state
1854         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1855         memset(&r_skinframe, 0, sizeof(r_skinframe));
1856
1857         if (r_svbsp.nodes)
1858                 Mem_Free(r_svbsp.nodes);
1859         memset(&r_svbsp, 0, sizeof (r_svbsp));
1860         R_FreeTexturePool(&r_main_texturepool);
1861         r_texture_blanknormalmap = NULL;
1862         r_texture_white = NULL;
1863         r_texture_grey128 = NULL;
1864         r_texture_black = NULL;
1865         r_texture_whitecube = NULL;
1866         r_texture_normalizationcube = NULL;
1867         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1868         memset(&r_waterstate, 0, sizeof(r_waterstate));
1869         R_GLSL_Restart_f();
1870 }
1871
1872 extern void CL_ParseEntityLump(char *entitystring);
1873 void gl_main_newmap(void)
1874 {
1875         // FIXME: move this code to client
1876         int l;
1877         char *entities, entname[MAX_QPATH];
1878         if (cl.worldmodel)
1879         {
1880                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1881                 l = (int)strlen(entname) - 4;
1882                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1883                 {
1884                         memcpy(entname + l, ".ent", 5);
1885                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1886                         {
1887                                 CL_ParseEntityLump(entities);
1888                                 Mem_Free(entities);
1889                                 return;
1890                         }
1891                 }
1892                 if (cl.worldmodel->brush.entities)
1893                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
1894         }
1895 }
1896
1897 void GL_Main_Init(void)
1898 {
1899         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1900
1901         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1902         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1903         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1904         if (gamemode == GAME_NEHAHRA)
1905         {
1906                 Cvar_RegisterVariable (&gl_fogenable);
1907                 Cvar_RegisterVariable (&gl_fogdensity);
1908                 Cvar_RegisterVariable (&gl_fogred);
1909                 Cvar_RegisterVariable (&gl_foggreen);
1910                 Cvar_RegisterVariable (&gl_fogblue);
1911                 Cvar_RegisterVariable (&gl_fogstart);
1912                 Cvar_RegisterVariable (&gl_fogend);
1913         }
1914         Cvar_RegisterVariable(&r_depthfirst);
1915         Cvar_RegisterVariable(&r_nearclip);
1916         Cvar_RegisterVariable(&r_showbboxes);
1917         Cvar_RegisterVariable(&r_showsurfaces);
1918         Cvar_RegisterVariable(&r_showtris);
1919         Cvar_RegisterVariable(&r_shownormals);
1920         Cvar_RegisterVariable(&r_showlighting);
1921         Cvar_RegisterVariable(&r_showshadowvolumes);
1922         Cvar_RegisterVariable(&r_showcollisionbrushes);
1923         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1924         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1925         Cvar_RegisterVariable(&r_showdisabledepthtest);
1926         Cvar_RegisterVariable(&r_drawportals);
1927         Cvar_RegisterVariable(&r_drawentities);
1928         Cvar_RegisterVariable(&r_cullentities_trace);
1929         Cvar_RegisterVariable(&r_cullentities_trace_samples);
1930         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1931         Cvar_RegisterVariable(&r_cullentities_trace_delay);
1932         Cvar_RegisterVariable(&r_drawviewmodel);
1933         Cvar_RegisterVariable(&r_speeds);
1934         Cvar_RegisterVariable(&r_fullbrights);
1935         Cvar_RegisterVariable(&r_wateralpha);
1936         Cvar_RegisterVariable(&r_dynamic);
1937         Cvar_RegisterVariable(&r_fullbright);
1938         Cvar_RegisterVariable(&r_shadows);
1939         Cvar_RegisterVariable(&r_shadows_throwdistance);
1940         Cvar_RegisterVariable(&r_q1bsp_skymasking);
1941         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1942         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1943         Cvar_RegisterVariable(&r_textureunits);
1944         Cvar_RegisterVariable(&r_glsl);
1945         Cvar_RegisterVariable(&r_glsl_offsetmapping);
1946         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1947         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1948         Cvar_RegisterVariable(&r_glsl_deluxemapping);
1949         Cvar_RegisterVariable(&r_water);
1950         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
1951         Cvar_RegisterVariable(&r_water_clippingplanebias);
1952         Cvar_RegisterVariable(&r_water_refractdistort);
1953         Cvar_RegisterVariable(&r_water_reflectdistort);
1954         Cvar_RegisterVariable(&r_lerpsprites);
1955         Cvar_RegisterVariable(&r_lerpmodels);
1956         Cvar_RegisterVariable(&r_waterscroll);
1957         Cvar_RegisterVariable(&r_bloom);
1958         Cvar_RegisterVariable(&r_bloom_colorscale);
1959         Cvar_RegisterVariable(&r_bloom_brighten);
1960         Cvar_RegisterVariable(&r_bloom_blur);
1961         Cvar_RegisterVariable(&r_bloom_resolution);
1962         Cvar_RegisterVariable(&r_bloom_colorexponent);
1963         Cvar_RegisterVariable(&r_bloom_colorsubtract);
1964         Cvar_RegisterVariable(&r_hdr);
1965         Cvar_RegisterVariable(&r_hdr_scenebrightness);
1966         Cvar_RegisterVariable(&r_glsl_contrastboost);
1967         Cvar_RegisterVariable(&r_hdr_glowintensity);
1968         Cvar_RegisterVariable(&r_hdr_range);
1969         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1970         Cvar_RegisterVariable(&developer_texturelogging);
1971         Cvar_RegisterVariable(&gl_lightmaps);
1972         Cvar_RegisterVariable(&r_test);
1973         Cvar_RegisterVariable(&r_batchmode);
1974         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1975                 Cvar_SetValue("r_fullbrights", 0);
1976         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1977
1978         Cvar_RegisterVariable(&r_track_sprites);
1979         Cvar_RegisterVariable(&r_track_sprites_flags);
1980         Cvar_RegisterVariable(&r_track_sprites_scalew);
1981         Cvar_RegisterVariable(&r_track_sprites_scaleh);
1982 }
1983
1984 extern void R_Textures_Init(void);
1985 extern void GL_Draw_Init(void);
1986 extern void GL_Main_Init(void);
1987 extern void R_Shadow_Init(void);
1988 extern void R_Sky_Init(void);
1989 extern void GL_Surf_Init(void);
1990 extern void R_Light_Init(void);
1991 extern void R_Particles_Init(void);
1992 extern void R_Explosion_Init(void);
1993 extern void gl_backend_init(void);
1994 extern void Sbar_Init(void);
1995 extern void R_LightningBeams_Init(void);
1996 extern void Mod_RenderInit(void);
1997
1998 void Render_Init(void)
1999 {
2000         gl_backend_init();
2001         R_Textures_Init();
2002         GL_Main_Init();
2003         GL_Draw_Init();
2004         R_Shadow_Init();
2005         R_Sky_Init();
2006         GL_Surf_Init();
2007         Sbar_Init();
2008         R_Light_Init();
2009         R_Particles_Init();
2010         R_Explosion_Init();
2011         R_LightningBeams_Init();
2012         Mod_RenderInit();
2013 }
2014
2015 /*
2016 ===============
2017 GL_Init
2018 ===============
2019 */
2020 extern char *ENGINE_EXTENSIONS;
2021 void GL_Init (void)
2022 {
2023         VID_CheckExtensions();
2024
2025         // LordHavoc: report supported extensions
2026         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2027
2028         // clear to black (loading plaque will be seen over this)
2029         CHECKGLERROR
2030         qglClearColor(0,0,0,1);CHECKGLERROR
2031         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2032 }
2033
2034 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2035 {
2036         int i;
2037         mplane_t *p;
2038         for (i = 0;i < r_view.numfrustumplanes;i++)
2039         {
2040                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2041                 if (i == 4)
2042                         continue;
2043                 p = r_view.frustum + i;
2044                 switch(p->signbits)
2045                 {
2046                 default:
2047                 case 0:
2048                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2049                                 return true;
2050                         break;
2051                 case 1:
2052                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2053                                 return true;
2054                         break;
2055                 case 2:
2056                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2057                                 return true;
2058                         break;
2059                 case 3:
2060                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2061                                 return true;
2062                         break;
2063                 case 4:
2064                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2065                                 return true;
2066                         break;
2067                 case 5:
2068                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2069                                 return true;
2070                         break;
2071                 case 6:
2072                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2073                                 return true;
2074                         break;
2075                 case 7:
2076                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2077                                 return true;
2078                         break;
2079                 }
2080         }
2081         return false;
2082 }
2083
2084 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2085 {
2086         int i;
2087         const mplane_t *p;
2088         for (i = 0;i < numplanes;i++)
2089         {
2090                 p = planes + i;
2091                 switch(p->signbits)
2092                 {
2093                 default:
2094                 case 0:
2095                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2096                                 return true;
2097                         break;
2098                 case 1:
2099                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2100                                 return true;
2101                         break;
2102                 case 2:
2103                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2104                                 return true;
2105                         break;
2106                 case 3:
2107                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2108                                 return true;
2109                         break;
2110                 case 4:
2111                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2112                                 return true;
2113                         break;
2114                 case 5:
2115                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2116                                 return true;
2117                         break;
2118                 case 6:
2119                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2120                                 return true;
2121                         break;
2122                 case 7:
2123                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2124                                 return true;
2125                         break;
2126                 }
2127         }
2128         return false;
2129 }
2130
2131 //==================================================================================
2132
2133 static void R_UpdateEntityLighting(entity_render_t *ent)
2134 {
2135         vec3_t tempdiffusenormal;
2136
2137         // fetch the lighting from the worldmodel data
2138         VectorSet(ent->modellight_ambient, r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f));
2139         VectorClear(ent->modellight_diffuse);
2140         VectorClear(tempdiffusenormal);
2141         if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
2142         {
2143                 vec3_t org;
2144                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2145                 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2146         }
2147         else // highly rare
2148                 VectorSet(ent->modellight_ambient, 1, 1, 1);
2149
2150         // move the light direction into modelspace coordinates for lighting code
2151         Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2152         if(VectorLength2(ent->modellight_lightdir) > 0)
2153         {
2154                 VectorNormalize(ent->modellight_lightdir);
2155         }
2156         else
2157         {
2158                 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2159         }
2160
2161         // scale ambient and directional light contributions according to rendering variables
2162         ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2163         ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2164         ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2165         ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2166         ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2167         ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2168 }
2169
2170 static void R_View_UpdateEntityVisible (void)
2171 {
2172         int i, renderimask;
2173         entity_render_t *ent;
2174
2175         if (!r_drawentities.integer)
2176                 return;
2177
2178         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2179         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
2180         {
2181                 // worldmodel can check visibility
2182                 for (i = 0;i < r_refdef.numentities;i++)
2183                 {
2184                         ent = r_refdef.entities[i];
2185                         r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((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)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
2186
2187                 }
2188                 if(r_cullentities_trace.integer)
2189                 {
2190                         for (i = 0;i < r_refdef.numentities;i++)
2191                         {
2192                                 ent = r_refdef.entities[i];
2193                                 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2194                                 {
2195                                         if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2196                                                 ent->last_trace_visibility = realtime;
2197                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2198                                                 r_viewcache.entityvisible[i] = 0;
2199                                 }
2200                         }
2201                 }
2202         }
2203         else
2204         {
2205                 // no worldmodel or it can't check visibility
2206                 for (i = 0;i < r_refdef.numentities;i++)
2207                 {
2208                         ent = r_refdef.entities[i];
2209                         r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((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));
2210                 }
2211         }
2212
2213         // update entity lighting (even on hidden entities for r_shadows)
2214         for (i = 0;i < r_refdef.numentities;i++)
2215                 R_UpdateEntityLighting(r_refdef.entities[i]);
2216 }
2217
2218 // only used if skyrendermasked, and normally returns false
2219 int R_DrawBrushModelsSky (void)
2220 {
2221         int i, sky;
2222         entity_render_t *ent;
2223
2224         if (!r_drawentities.integer)
2225                 return false;
2226
2227         sky = false;
2228         for (i = 0;i < r_refdef.numentities;i++)
2229         {
2230                 if (!r_viewcache.entityvisible[i])
2231                         continue;
2232                 ent = r_refdef.entities[i];
2233                 if (!ent->model || !ent->model->DrawSky)
2234                         continue;
2235                 ent->model->DrawSky(ent);
2236                 sky = true;
2237         }
2238         return sky;
2239 }
2240
2241 static void R_DrawNoModel(entity_render_t *ent);
2242 static void R_DrawModels(void)
2243 {
2244         int i;
2245         entity_render_t *ent;
2246
2247         if (!r_drawentities.integer)
2248                 return;
2249
2250         for (i = 0;i < r_refdef.numentities;i++)
2251         {
2252                 if (!r_viewcache.entityvisible[i])
2253                         continue;
2254                 ent = r_refdef.entities[i];
2255                 r_refdef.stats.entities++;
2256                 if (ent->model && ent->model->Draw != NULL)
2257                         ent->model->Draw(ent);
2258                 else
2259                         R_DrawNoModel(ent);
2260         }
2261 }
2262
2263 static void R_DrawModelsDepth(void)
2264 {
2265         int i;
2266         entity_render_t *ent;
2267
2268         if (!r_drawentities.integer)
2269                 return;
2270
2271         for (i = 0;i < r_refdef.numentities;i++)
2272         {
2273                 if (!r_viewcache.entityvisible[i])
2274                         continue;
2275                 ent = r_refdef.entities[i];
2276                 if (ent->model && ent->model->DrawDepth != NULL)
2277                         ent->model->DrawDepth(ent);
2278         }
2279 }
2280
2281 static void R_DrawModelsDebug(void)
2282 {
2283         int i;
2284         entity_render_t *ent;
2285
2286         if (!r_drawentities.integer)
2287                 return;
2288
2289         for (i = 0;i < r_refdef.numentities;i++)
2290         {
2291                 if (!r_viewcache.entityvisible[i])
2292                         continue;
2293                 ent = r_refdef.entities[i];
2294                 if (ent->model && ent->model->DrawDebug != NULL)
2295                         ent->model->DrawDebug(ent);
2296         }
2297 }
2298
2299 static void R_DrawModelsAddWaterPlanes(void)
2300 {
2301         int i;
2302         entity_render_t *ent;
2303
2304         if (!r_drawentities.integer)
2305                 return;
2306
2307         for (i = 0;i < r_refdef.numentities;i++)
2308         {
2309                 if (!r_viewcache.entityvisible[i])
2310                         continue;
2311                 ent = r_refdef.entities[i];
2312                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2313                         ent->model->DrawAddWaterPlanes(ent);
2314         }
2315 }
2316
2317 static void R_View_SetFrustum(void)
2318 {
2319         int i;
2320         double slopex, slopey;
2321
2322         // break apart the view matrix into vectors for various purposes
2323         Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2324         VectorNegate(r_view.left, r_view.right);
2325
2326 #if 0
2327         r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2328         r_view.frustum[0].normal[1] = 0 - 0;
2329         r_view.frustum[0].normal[2] = -1 - 0;
2330         r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2331         r_view.frustum[1].normal[1] = 0 + 0;
2332         r_view.frustum[1].normal[2] = -1 + 0;
2333         r_view.frustum[2].normal[0] = 0 - 0;
2334         r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2335         r_view.frustum[2].normal[2] = -1 - 0;
2336         r_view.frustum[3].normal[0] = 0 + 0;
2337         r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2338         r_view.frustum[3].normal[2] = -1 + 0;
2339 #endif
2340
2341 #if 0
2342         zNear = r_refdef.nearclip;
2343         nudge = 1.0 - 1.0 / (1<<23);
2344         r_view.frustum[4].normal[0] = 0 - 0;
2345         r_view.frustum[4].normal[1] = 0 - 0;
2346         r_view.frustum[4].normal[2] = -1 - -nudge;
2347         r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2348         r_view.frustum[5].normal[0] = 0 + 0;
2349         r_view.frustum[5].normal[1] = 0 + 0;
2350         r_view.frustum[5].normal[2] = -1 + -nudge;
2351         r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2352 #endif
2353
2354
2355
2356 #if 0
2357         r_view.frustum[0].normal[0] = m[3] - m[0];
2358         r_view.frustum[0].normal[1] = m[7] - m[4];
2359         r_view.frustum[0].normal[2] = m[11] - m[8];
2360         r_view.frustum[0].dist = m[15] - m[12];
2361
2362         r_view.frustum[1].normal[0] = m[3] + m[0];
2363         r_view.frustum[1].normal[1] = m[7] + m[4];
2364         r_view.frustum[1].normal[2] = m[11] + m[8];
2365         r_view.frustum[1].dist = m[15] + m[12];
2366
2367         r_view.frustum[2].normal[0] = m[3] - m[1];
2368         r_view.frustum[2].normal[1] = m[7] - m[5];
2369         r_view.frustum[2].normal[2] = m[11] - m[9];
2370         r_view.frustum[2].dist = m[15] - m[13];
2371
2372         r_view.frustum[3].normal[0] = m[3] + m[1];
2373         r_view.frustum[3].normal[1] = m[7] + m[5];
2374         r_view.frustum[3].normal[2] = m[11] + m[9];
2375         r_view.frustum[3].dist = m[15] + m[13];
2376
2377         r_view.frustum[4].normal[0] = m[3] - m[2];
2378         r_view.frustum[4].normal[1] = m[7] - m[6];
2379         r_view.frustum[4].normal[2] = m[11] - m[10];
2380         r_view.frustum[4].dist = m[15] - m[14];
2381
2382         r_view.frustum[5].normal[0] = m[3] + m[2];
2383         r_view.frustum[5].normal[1] = m[7] + m[6];
2384         r_view.frustum[5].normal[2] = m[11] + m[10];
2385         r_view.frustum[5].dist = m[15] + m[14];
2386 #endif
2387
2388         if (r_view.useperspective)
2389         {
2390                 slopex = 1.0 / r_view.frustum_x;
2391                 slopey = 1.0 / r_view.frustum_y;
2392                 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2393                 VectorMA(r_view.forward,  slopex, r_view.left, r_view.frustum[1].normal);
2394                 VectorMA(r_view.forward, -slopey, r_view.up  , r_view.frustum[2].normal);
2395                 VectorMA(r_view.forward,  slopey, r_view.up  , r_view.frustum[3].normal);
2396                 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2397                 
2398                 // Leaving those out was a mistake, those were in the old code, and they
2399                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2400                 // I couldn't reproduce it after adding those normalizations. --blub
2401                 VectorNormalize(r_view.frustum[0].normal);
2402                 VectorNormalize(r_view.frustum[1].normal);
2403                 VectorNormalize(r_view.frustum[2].normal);
2404                 VectorNormalize(r_view.frustum[3].normal);
2405
2406                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2407                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2408                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward,  1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2409                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left,  1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2410                 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward,  1024 * slopex, r_view.left,  1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2411
2412                 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2413                 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2414                 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2415                 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2416                 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2417         }
2418         else
2419         {
2420                 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2421                 VectorScale(r_view.left,  r_view.ortho_x, r_view.frustum[1].normal);
2422                 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2423                 VectorScale(r_view.up,  r_view.ortho_y, r_view.frustum[3].normal);
2424                 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2425                 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2426                 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2427                 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2428                 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2429                 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2430         }
2431         r_view.numfrustumplanes = 5;
2432
2433         if (r_view.useclipplane)
2434         {
2435                 r_view.numfrustumplanes = 6;
2436                 r_view.frustum[5] = r_view.clipplane;
2437         }
2438
2439         for (i = 0;i < r_view.numfrustumplanes;i++)
2440                 PlaneClassify(r_view.frustum + i);
2441
2442         // LordHavoc: note to all quake engine coders, Quake had a special case
2443         // for 90 degrees which assumed a square view (wrong), so I removed it,
2444         // Quake2 has it disabled as well.
2445
2446         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2447         //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2448         //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2449         //PlaneClassify(&frustum[0]);
2450
2451         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2452         //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2453         //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2454         //PlaneClassify(&frustum[1]);
2455
2456         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2457         //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2458         //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2459         //PlaneClassify(&frustum[2]);
2460
2461         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2462         //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2463         //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2464         //PlaneClassify(&frustum[3]);
2465
2466         // nearclip plane
2467         //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2468         //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2469         //PlaneClassify(&frustum[4]);
2470 }
2471
2472 void R_View_Update(void)
2473 {
2474         R_View_SetFrustum();
2475         R_View_WorldVisibility(r_view.useclipplane);
2476         R_View_UpdateEntityVisible();
2477 }
2478
2479 void R_SetupView(void)
2480 {
2481         if (!r_view.useperspective)
2482                 GL_SetupView_Mode_Ortho(-r_view.ortho_x, -r_view.ortho_y, r_view.ortho_x, r_view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2483         else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2484                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2485         else
2486                 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2487
2488         GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2489
2490         if (r_view.useclipplane)
2491         {
2492                 // LordHavoc: couldn't figure out how to make this approach the
2493                 vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
2494                 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2495                 if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
2496                         dist = r_view.clipplane.dist;
2497                 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2498         }
2499 }
2500
2501 void R_ResetViewRendering2D(void)
2502 {
2503         if (gl_support_fragment_shader)
2504         {
2505                 qglUseProgramObjectARB(0);CHECKGLERROR
2506         }
2507
2508         DrawQ_Finish();
2509
2510         // GL is weird because it's bottom to top, r_view.y is top to bottom
2511         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2512         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2513         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2514         GL_Color(1, 1, 1, 1);
2515         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2516         GL_BlendFunc(GL_ONE, GL_ZERO);
2517         GL_AlphaTest(false);
2518         GL_ScissorTest(false);
2519         GL_DepthMask(false);
2520         GL_DepthRange(0, 1);
2521         GL_DepthTest(false);
2522         R_Mesh_Matrix(&identitymatrix);
2523         R_Mesh_ResetTextureState();
2524         GL_PolygonOffset(0, 0);
2525         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2526         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2527         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2528         qglStencilMask(~0);CHECKGLERROR
2529         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2530         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2531         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2532 }
2533
2534 void R_ResetViewRendering3D(void)
2535 {
2536         if (gl_support_fragment_shader)
2537         {
2538                 qglUseProgramObjectARB(0);CHECKGLERROR
2539         }
2540
2541         DrawQ_Finish();
2542
2543         // GL is weird because it's bottom to top, r_view.y is top to bottom
2544         qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2545         R_SetupView();
2546         GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2547         GL_Color(1, 1, 1, 1);
2548         GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2549         GL_BlendFunc(GL_ONE, GL_ZERO);
2550         GL_AlphaTest(false);
2551         GL_ScissorTest(true);
2552         GL_DepthMask(true);
2553         GL_DepthRange(0, 1);
2554         GL_DepthTest(true);
2555         R_Mesh_Matrix(&identitymatrix);
2556         R_Mesh_ResetTextureState();
2557         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2558         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2559         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2560         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2561         qglStencilMask(~0);CHECKGLERROR
2562         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2563         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2564         GL_CullFace(r_view.cullface_back);
2565 }
2566
2567 /*
2568         R_Bloom_SetupShader(
2569 "// bloom shader\n"
2570 "// written by Forest 'LordHavoc' Hale\n"
2571 "\n"
2572 "// common definitions between vertex shader and fragment shader:\n"
2573 "\n"
2574 "#ifdef __GLSL_CG_DATA_TYPES\n"
2575 "#define myhalf half\n"
2576 "#define myhvec2 hvec2\n"
2577 "#define myhvec3 hvec3\n"
2578 "#define myhvec4 hvec4\n"
2579 "#else\n"
2580 "#define myhalf float\n"
2581 "#define myhvec2 vec2\n"
2582 "#define myhvec3 vec3\n"
2583 "#define myhvec4 vec4\n"
2584 "#endif\n"
2585 "\n"
2586 "varying vec2 ScreenTexCoord;\n"
2587 "varying vec2 BloomTexCoord;\n"
2588 "\n"
2589 "\n"
2590 "\n"
2591 "\n"
2592 "// vertex shader specific:\n"
2593 "#ifdef VERTEX_SHADER\n"
2594 "\n"
2595 "void main(void)\n"
2596 "{\n"
2597 "       ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2598 "       BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2599 "       // transform vertex to camera space, using ftransform to match non-VS\n"
2600 "       // rendering\n"
2601 "       gl_Position = ftransform();\n"
2602 "}\n"
2603 "\n"
2604 "#endif // VERTEX_SHADER\n"
2605 "\n"
2606 "\n"
2607 "\n"
2608 "\n"
2609 "// fragment shader specific:\n"
2610 "#ifdef FRAGMENT_SHADER\n"
2611 "\n"
2612 "void main(void)\n"
2613 "{\n"
2614 "       int x, y;
2615 "       myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2616 "       for (x = -BLUR_X;x <= BLUR_X;x++)
2617 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2618 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2619 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2620 "       color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2621
2622 "       gl_FragColor = vec4(color);\n"
2623 "}\n"
2624 "\n"
2625 "#endif // FRAGMENT_SHADER\n"
2626 */
2627
2628 void R_RenderScene(qboolean addwaterplanes);
2629
2630 static void R_Water_StartFrame(void)
2631 {
2632         int i;
2633         int waterwidth, waterheight, texturewidth, textureheight;
2634         r_waterstate_waterplane_t *p;
2635
2636         // set waterwidth and waterheight to the water resolution that will be
2637         // used (often less than the screen resolution for faster rendering)
2638         waterwidth = (int)bound(1, r_view.width * r_water_resolutionmultiplier.value, r_view.width);
2639         waterheight = (int)bound(1, r_view.height * r_water_resolutionmultiplier.value, r_view.height);
2640
2641         // calculate desired texture sizes
2642         // can't use water if the card does not support the texture size
2643         if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2644                 texturewidth = textureheight = waterwidth = waterheight = 0;
2645         else if (gl_support_arb_texture_non_power_of_two)
2646         {
2647                 texturewidth = waterwidth;
2648                 textureheight = waterheight;
2649         }
2650         else
2651         {
2652                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
2653                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
2654         }
2655
2656         // allocate textures as needed
2657         if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2658         {
2659                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2660                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2661                 {
2662                         if (p->texture_refraction)
2663                                 R_FreeTexture(p->texture_refraction);
2664                         p->texture_refraction = NULL;
2665                         if (p->texture_reflection)
2666                                 R_FreeTexture(p->texture_reflection);
2667                         p->texture_reflection = NULL;
2668                 }
2669                 memset(&r_waterstate, 0, sizeof(r_waterstate));
2670                 r_waterstate.waterwidth = waterwidth;
2671                 r_waterstate.waterheight = waterheight;
2672                 r_waterstate.texturewidth = texturewidth;
2673                 r_waterstate.textureheight = textureheight;
2674         }
2675
2676         if (r_waterstate.waterwidth)
2677         {
2678                 r_waterstate.enabled = true;
2679
2680                 // set up variables that will be used in shader setup
2681                 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2682                 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2683                 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2684                 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2685         }
2686
2687         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2688         r_waterstate.numwaterplanes = 0;
2689 }
2690
2691 static void R_Water_AddWaterPlane(msurface_t *surface)
2692 {
2693         int triangleindex, planeindex;
2694         const int *e;
2695         vec_t f;
2696         vec3_t vert[3];
2697         vec3_t normal;
2698         vec3_t center;
2699         r_waterstate_waterplane_t *p;
2700         // just use the first triangle with a valid normal for any decisions
2701         VectorClear(normal);
2702         VectorClear(center);
2703         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2704         {
2705                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2706                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2707                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2708                 TriangleNormal(vert[0], vert[1], vert[2], normal);
2709                 if (VectorLength2(normal) >= 0.001)
2710                         break;
2711         }
2712         // now find the center of this surface
2713         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2714         {
2715                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2716                 VectorAdd(center, vert[0], center);
2717         }
2718         f = 1.0 / surface->num_triangles*3;
2719         VectorScale(center, f, center);
2720
2721         // find a matching plane if there is one
2722         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2723                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2724                         break;
2725         if (planeindex >= r_waterstate.maxwaterplanes)
2726                 return; // nothing we can do, out of planes
2727
2728         // if this triangle does not fit any known plane rendered this frame, add one
2729         if (planeindex >= r_waterstate.numwaterplanes)
2730         {
2731                 // store the new plane
2732                 r_waterstate.numwaterplanes++;
2733                 VectorCopy(normal, p->plane.normal);
2734                 VectorNormalize(p->plane.normal);
2735                 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2736                 PlaneClassify(&p->plane);
2737                 // flip the plane if it does not face the viewer
2738                 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2739                 {
2740                         VectorNegate(p->plane.normal, p->plane.normal);
2741                         p->plane.dist *= -1;
2742                         PlaneClassify(&p->plane);
2743                 }
2744                 // clear materialflags and pvs
2745                 p->materialflags = 0;
2746                 p->pvsvalid = false;
2747         }
2748         // merge this surface's materialflags into the waterplane
2749         p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2750         // merge this surface's PVS into the waterplane
2751         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2752         {
2753                 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2754                 p->pvsvalid = true;
2755         }
2756 }
2757
2758 static void R_Water_ProcessPlanes(void)
2759 {
2760         r_view_t originalview;
2761         int planeindex;
2762         r_waterstate_waterplane_t *p;
2763
2764         originalview = r_view;
2765
2766         // make sure enough textures are allocated
2767         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2768         {
2769                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2770                 {
2771                         if (!p->texture_refraction)
2772                                 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);
2773                         if (!p->texture_refraction)
2774                                 goto error;
2775                 }
2776
2777                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2778                 {
2779                         if (!p->texture_reflection)
2780                                 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);
2781                         if (!p->texture_reflection)
2782                                 goto error;
2783                 }
2784         }
2785
2786         // render views
2787         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2788         {
2789                 r_view.showdebug = false;
2790                 r_view.width = r_waterstate.waterwidth;
2791                 r_view.height = r_waterstate.waterheight;
2792                 r_view.useclipplane = true;
2793                 r_waterstate.renderingscene = true;
2794
2795                 // render the normal view scene and copy into texture
2796                 // (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)
2797                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2798                 {
2799                         r_view.clipplane = p->plane;
2800                         VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2801                         r_view.clipplane.dist = -r_view.clipplane.dist;
2802                         PlaneClassify(&r_view.clipplane);
2803
2804                         R_RenderScene(false);
2805
2806                         // copy view into the screen texture
2807                         R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2808                         GL_ActiveTexture(0);
2809                         CHECKGLERROR
2810                         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2811                 }
2812
2813                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2814                 {
2815                         // render reflected scene and copy into texture
2816                         Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2817                         r_view.clipplane = p->plane;
2818                         // reverse the cullface settings for this render
2819                         r_view.cullface_front = GL_FRONT;
2820                         r_view.cullface_back = GL_BACK;
2821                         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2822                         {
2823                                 r_view.usecustompvs = true;
2824                                 if (p->pvsvalid)
2825                                         memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2826                                 else
2827                                         memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2828                         }
2829
2830                         R_ResetViewRendering3D();
2831                         R_ClearScreen();
2832                         if (r_timereport_active)
2833                                 R_TimeReport("viewclear");
2834
2835                         R_RenderScene(false);
2836
2837                         R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2838                         GL_ActiveTexture(0);
2839                         CHECKGLERROR
2840                         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2841
2842                         R_ResetViewRendering3D();
2843                         R_ClearScreen();
2844                         if (r_timereport_active)
2845                                 R_TimeReport("viewclear");
2846                 }
2847
2848                 r_view = originalview;
2849                 r_view.clear = true;
2850                 r_waterstate.renderingscene = false;
2851         }
2852         return;
2853 error:
2854         r_view = originalview;
2855         r_waterstate.renderingscene = false;
2856         Cvar_SetValueQuick(&r_water, 0);
2857         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
2858         return;
2859 }
2860
2861 void R_Bloom_StartFrame(void)
2862 {
2863         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2864
2865         // set bloomwidth and bloomheight to the bloom resolution that will be
2866         // used (often less than the screen resolution for faster rendering)
2867         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2868         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2869         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2870
2871         // calculate desired texture sizes
2872         if (gl_support_arb_texture_non_power_of_two)
2873         {
2874                 screentexturewidth = r_view.width;
2875                 screentextureheight = r_view.height;
2876                 bloomtexturewidth = r_bloomstate.bloomwidth;
2877                 bloomtextureheight = r_bloomstate.bloomheight;
2878         }
2879         else
2880         {
2881                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
2882                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
2883                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
2884                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
2885         }
2886
2887         if (r_hdr.integer)
2888         {
2889                 screentexturewidth = screentextureheight = 0;
2890         }
2891         else if (r_bloom.integer)
2892         {
2893         }
2894         else
2895         {
2896                 screentexturewidth = screentextureheight = 0;
2897                 bloomtexturewidth = bloomtextureheight = 0;
2898         }
2899
2900         if ((!bloomtexturewidth && !bloomtextureheight) || r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512 || screentexturewidth > gl_max_texture_size || screentextureheight > gl_max_texture_size || bloomtexturewidth > gl_max_texture_size || bloomtextureheight > gl_max_texture_size)
2901         {
2902                 // can't use bloom if the parameters are too weird
2903                 // can't use bloom if the card does not support the texture size
2904                 if (r_bloomstate.texture_screen)
2905                         R_FreeTexture(r_bloomstate.texture_screen);
2906                 if (r_bloomstate.texture_bloom)
2907                         R_FreeTexture(r_bloomstate.texture_bloom);
2908                 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2909                 return;
2910         }
2911
2912         r_bloomstate.enabled = true;
2913         r_bloomstate.hdr = r_hdr.integer != 0;
2914
2915         // allocate textures as needed
2916         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2917         {
2918                 if (r_bloomstate.texture_screen)
2919                         R_FreeTexture(r_bloomstate.texture_screen);
2920                 r_bloomstate.texture_screen = NULL;
2921                 r_bloomstate.screentexturewidth = screentexturewidth;
2922                 r_bloomstate.screentextureheight = screentextureheight;
2923                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2924                         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);
2925         }
2926         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2927         {
2928                 if (r_bloomstate.texture_bloom)
2929                         R_FreeTexture(r_bloomstate.texture_bloom);
2930                 r_bloomstate.texture_bloom = NULL;
2931                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2932                 r_bloomstate.bloomtextureheight = bloomtextureheight;
2933                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2934                         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);
2935         }
2936
2937         // set up a texcoord array for the full resolution screen image
2938         // (we have to keep this around to copy back during final render)
2939         r_bloomstate.screentexcoord2f[0] = 0;
2940         r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2941         r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2942         r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2943         r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2944         r_bloomstate.screentexcoord2f[5] = 0;
2945         r_bloomstate.screentexcoord2f[6] = 0;
2946         r_bloomstate.screentexcoord2f[7] = 0;
2947
2948         // set up a texcoord array for the reduced resolution bloom image
2949         // (which will be additive blended over the screen image)
2950         r_bloomstate.bloomtexcoord2f[0] = 0;
2951         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2952         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2953         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2954         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2955         r_bloomstate.bloomtexcoord2f[5] = 0;
2956         r_bloomstate.bloomtexcoord2f[6] = 0;
2957         r_bloomstate.bloomtexcoord2f[7] = 0;
2958 }
2959
2960 void R_Bloom_CopyScreenTexture(float colorscale)
2961 {
2962         r_refdef.stats.bloom++;
2963
2964         R_ResetViewRendering2D();
2965         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2966         R_Mesh_ColorPointer(NULL, 0, 0);
2967         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2968         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2969
2970         // copy view into the screen texture
2971         GL_ActiveTexture(0);
2972         CHECKGLERROR
2973         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2974         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2975
2976         // now scale it down to the bloom texture size
2977         CHECKGLERROR
2978         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2979         GL_BlendFunc(GL_ONE, GL_ZERO);
2980         GL_Color(colorscale, colorscale, colorscale, 1);
2981         // TODO: optimize with multitexture or GLSL
2982         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2983         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2984
2985         // we now have a bloom image in the framebuffer
2986         // copy it into the bloom image texture for later processing
2987         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2988         GL_ActiveTexture(0);
2989         CHECKGLERROR
2990         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2991         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2992 }
2993
2994 void R_Bloom_CopyHDRTexture(void)
2995 {
2996         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2997         GL_ActiveTexture(0);
2998         CHECKGLERROR
2999         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
3000         r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
3001 }
3002
3003 void R_Bloom_MakeTexture(void)
3004 {
3005         int x, range, dir;
3006         float xoffset, yoffset, r, brighten;
3007
3008         r_refdef.stats.bloom++;
3009
3010         R_ResetViewRendering2D();
3011         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3012         R_Mesh_ColorPointer(NULL, 0, 0);
3013
3014         // we have a bloom image in the framebuffer
3015         CHECKGLERROR
3016         qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3017
3018         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3019         {
3020                 x *= 2;
3021                 r = bound(0, r_bloom_colorexponent.value / x, 1);
3022                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3023                 GL_Color(r, r, r, 1);
3024                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3025                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3026                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3027                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3028
3029                 // copy the vertically blurred bloom view to a texture
3030                 GL_ActiveTexture(0);
3031                 CHECKGLERROR
3032                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3033                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3034         }
3035
3036         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3037         brighten = r_bloom_brighten.value;
3038         if (r_hdr.integer)
3039                 brighten *= r_hdr_range.value;
3040         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3041         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3042
3043         for (dir = 0;dir < 2;dir++)
3044         {
3045                 // blend on at multiple vertical offsets to achieve a vertical blur
3046                 // TODO: do offset blends using GLSL
3047                 GL_BlendFunc(GL_ONE, GL_ZERO);
3048                 for (x = -range;x <= range;x++)
3049                 {
3050                         if (!dir){xoffset = 0;yoffset = x;}
3051                         else {xoffset = x;yoffset = 0;}
3052                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
3053                         yoffset /= (float)r_bloomstate.bloomtextureheight;
3054                         // compute a texcoord array with the specified x and y offset
3055                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3056                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3057                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3058                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3059                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3060                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3061                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3062                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3063                         // this r value looks like a 'dot' particle, fading sharply to
3064                         // black at the edges
3065                         // (probably not realistic but looks good enough)
3066                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3067                         //r = (dir ? 1.0f : brighten)/(range*2+1);
3068                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3069                         GL_Color(r, r, r, 1);
3070                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3071                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3072                         GL_BlendFunc(GL_ONE, GL_ONE);
3073                 }
3074
3075                 // copy the vertically blurred bloom view to a texture
3076                 GL_ActiveTexture(0);
3077                 CHECKGLERROR
3078                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3079                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3080         }
3081
3082         // apply subtract last
3083         // (just like it would be in a GLSL shader)
3084         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3085         {
3086                 GL_BlendFunc(GL_ONE, GL_ZERO);
3087                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3088                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3089                 GL_Color(1, 1, 1, 1);
3090                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3091                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3092
3093                 GL_BlendFunc(GL_ONE, GL_ONE);
3094                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3095                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3096                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3097                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3098                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3099                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3100                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3101
3102                 // copy the darkened bloom view to a texture
3103                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3104                 GL_ActiveTexture(0);
3105                 CHECKGLERROR
3106                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3107                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3108         }
3109 }
3110
3111 void R_HDR_RenderBloomTexture(void)
3112 {
3113         int oldwidth, oldheight;
3114
3115         oldwidth = r_view.width;
3116         oldheight = r_view.height;
3117         r_view.width = r_bloomstate.bloomwidth;
3118         r_view.height = r_bloomstate.bloomheight;
3119
3120         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
3121         // TODO: add exposure compensation features
3122         // TODO: add fp16 framebuffer support
3123
3124         r_view.showdebug = false;
3125         r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
3126         if (r_hdr.integer)
3127                 r_view.colorscale /= r_hdr_range.value;
3128         r_waterstate.numwaterplanes = 0;
3129         R_RenderScene(r_waterstate.enabled);
3130         r_view.showdebug = true;
3131
3132         R_ResetViewRendering2D();
3133
3134         R_Bloom_CopyHDRTexture();
3135         R_Bloom_MakeTexture();
3136
3137         R_ResetViewRendering3D();
3138
3139         R_ClearScreen();
3140         if (r_timereport_active)
3141                 R_TimeReport("viewclear");
3142
3143         // restore the view settings
3144         r_view.width = oldwidth;
3145         r_view.height = oldheight;
3146 }
3147
3148 static void R_BlendView(void)
3149 {
3150         if (r_bloomstate.enabled && r_bloomstate.hdr)
3151         {
3152                 // render high dynamic range bloom effect
3153                 // the bloom texture was made earlier this render, so we just need to
3154                 // blend it onto the screen...
3155                 R_ResetViewRendering2D();
3156                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3157                 R_Mesh_ColorPointer(NULL, 0, 0);
3158                 GL_Color(1, 1, 1, 1);
3159                 GL_BlendFunc(GL_ONE, GL_ONE);
3160                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3161                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3162                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3163                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3164         }
3165         else if (r_bloomstate.enabled)
3166         {
3167                 // render simple bloom effect
3168                 // copy the screen and shrink it and darken it for the bloom process
3169                 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3170                 // make the bloom texture
3171                 R_Bloom_MakeTexture();
3172                 // put the original screen image back in place and blend the bloom
3173                 // texture on it
3174                 R_ResetViewRendering2D();
3175                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3176                 R_Mesh_ColorPointer(NULL, 0, 0);
3177                 GL_Color(1, 1, 1, 1);
3178                 GL_BlendFunc(GL_ONE, GL_ZERO);
3179                 // do both in one pass if possible
3180                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3181                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3182                 if (r_textureunits.integer >= 2 && gl_combine.integer)
3183                 {
3184                         R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3185                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3186                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3187                 }
3188                 else
3189                 {
3190                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3191                         r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3192                         // now blend on the bloom texture
3193                         GL_BlendFunc(GL_ONE, GL_ONE);
3194                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3195                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3196                 }
3197                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3198                 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3199         }
3200         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3201         {
3202                 // apply a color tint to the whole view
3203                 R_ResetViewRendering2D();
3204                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3205                 R_Mesh_ColorPointer(NULL, 0, 0);
3206                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3207                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3208                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3209         }
3210 }
3211
3212 void R_RenderScene(qboolean addwaterplanes);
3213
3214 matrix4x4_t r_waterscrollmatrix;
3215
3216 void R_UpdateVariables(void)
3217 {
3218         R_Textures_Frame();
3219
3220         r_refdef.farclip = 4096;
3221         if (r_refdef.worldmodel)
3222                 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3223         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3224
3225         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3226                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3227         r_refdef.polygonfactor = 0;
3228         r_refdef.polygonoffset = 0;
3229         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3230         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3231
3232         r_refdef.rtworld = r_shadow_realtime_world.integer;
3233         r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3234         r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3235         r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3236         r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3237         if (r_showsurfaces.integer)
3238         {
3239                 r_refdef.rtworld = false;
3240                 r_refdef.rtworldshadows = false;
3241                 r_refdef.rtdlight = false;
3242                 r_refdef.rtdlightshadows = false;
3243                 r_refdef.lightmapintensity = 0;
3244         }
3245
3246         if (gamemode == GAME_NEHAHRA)
3247         {
3248                 if (gl_fogenable.integer)
3249                 {
3250                         r_refdef.oldgl_fogenable = true;
3251                         r_refdef.fog_density = gl_fogdensity.value;
3252                         r_refdef.fog_red = gl_fogred.value;
3253                         r_refdef.fog_green = gl_foggreen.value;
3254                         r_refdef.fog_blue = gl_fogblue.value;
3255                 }
3256                 else if (r_refdef.oldgl_fogenable)
3257                 {
3258                         r_refdef.oldgl_fogenable = false;
3259                         r_refdef.fog_density = 0;
3260                         r_refdef.fog_red = 0;
3261                         r_refdef.fog_green = 0;
3262                         r_refdef.fog_blue = 0;
3263                 }
3264         }
3265         if (r_refdef.fog_density)
3266         {
3267                 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red  , 1.0f);
3268                 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3269                 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3270         }
3271         if (r_refdef.fog_density)
3272         {
3273                 r_refdef.fogenabled = true;
3274                 // this is the point where the fog reaches 0.9986 alpha, which we
3275                 // consider a good enough cutoff point for the texture
3276                 // (0.9986 * 256 == 255.6)
3277                 r_refdef.fogrange = 400 / r_refdef.fog_density;
3278                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3279                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3280                 // fog color was already set
3281         }
3282         else
3283                 r_refdef.fogenabled = false;
3284 }
3285
3286 /*
3287 ================
3288 R_RenderView
3289 ================
3290 */
3291 void R_RenderView(void)
3292 {
3293         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3294                 return; //Host_Error ("R_RenderView: NULL worldmodel");
3295
3296         R_Shadow_UpdateWorldLightSelection();
3297
3298         R_Bloom_StartFrame();
3299         R_Water_StartFrame();
3300
3301         CHECKGLERROR
3302         if (r_timereport_active)
3303                 R_TimeReport("viewsetup");
3304
3305         R_ResetViewRendering3D();
3306
3307         if (r_view.clear)
3308         {
3309                 R_ClearScreen();
3310                 if (r_timereport_active)
3311                         R_TimeReport("viewclear");
3312         }
3313         r_view.clear = true;
3314
3315         r_view.showdebug = true;
3316
3317         // this produces a bloom texture to be used in R_BlendView() later
3318         if (r_hdr.integer)
3319                 R_HDR_RenderBloomTexture();
3320
3321         r_view.colorscale = r_hdr_scenebrightness.value;
3322         r_waterstate.numwaterplanes = 0;
3323         R_RenderScene(r_waterstate.enabled);
3324
3325         R_BlendView();
3326         if (r_timereport_active)
3327                 R_TimeReport("blendview");
3328
3329         GL_Scissor(0, 0, vid.width, vid.height);
3330         GL_ScissorTest(false);
3331         CHECKGLERROR
3332 }
3333
3334 extern void R_DrawLightningBeams (void);
3335 extern void VM_CL_AddPolygonsToMeshQueue (void);
3336 extern void R_DrawPortals (void);
3337 extern cvar_t cl_locs_show;
3338 static void R_DrawLocs(void);
3339 static void R_DrawEntityBBoxes(void);
3340 void R_RenderScene(qboolean addwaterplanes)
3341 {
3342         if (addwaterplanes)
3343         {
3344                 R_ResetViewRendering3D();
3345
3346                 R_View_Update();
3347                 if (r_timereport_active)
3348                         R_TimeReport("watervis");
3349
3350                 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3351                 {
3352                         r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3353                         if (r_timereport_active)
3354                                 R_TimeReport("waterworld");
3355                 }
3356
3357                 // don't let sound skip if going slow
3358                 if (r_refdef.extraupdate)
3359                         S_ExtraUpdate ();
3360
3361                 R_DrawModelsAddWaterPlanes();
3362                 if (r_timereport_active)
3363                         R_TimeReport("watermodels");
3364
3365                 R_Water_ProcessPlanes();
3366                 if (r_timereport_active)
3367                         R_TimeReport("waterscenes");
3368         }
3369
3370         R_ResetViewRendering3D();
3371
3372         // don't let sound skip if going slow
3373         if (r_refdef.extraupdate)
3374                 S_ExtraUpdate ();
3375
3376         R_MeshQueue_BeginScene();
3377
3378         R_SkyStartFrame();
3379
3380         R_View_Update();
3381         if (r_timereport_active)
3382                 R_TimeReport("visibility");
3383
3384         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
3385
3386         if (cl.csqc_vidvars.drawworld)
3387         {
3388                 // don't let sound skip if going slow
3389                 if (r_refdef.extraupdate)
3390                         S_ExtraUpdate ();
3391
3392                 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3393                 {
3394                         r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3395                         if (r_timereport_active)
3396                                 R_TimeReport("worldsky");
3397                 }
3398
3399                 if (R_DrawBrushModelsSky() && r_timereport_active)
3400                         R_TimeReport("bmodelsky");
3401         }
3402
3403         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3404         {
3405                 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3406                 if (r_timereport_active)
3407                         R_TimeReport("worlddepth");
3408         }
3409         if (r_depthfirst.integer >= 2)
3410         {
3411                 R_DrawModelsDepth();
3412                 if (r_timereport_active)
3413                         R_TimeReport("modeldepth");
3414         }
3415
3416         if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3417         {
3418                 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3419                 if (r_timereport_active)
3420                         R_TimeReport("world");
3421         }
3422
3423         // don't let sound skip if going slow
3424         if (r_refdef.extraupdate)
3425                 S_ExtraUpdate ();
3426
3427         R_DrawModels();
3428         if (r_timereport_active)
3429                 R_TimeReport("models");
3430
3431         // don't let sound skip if going slow
3432         if (r_refdef.extraupdate)
3433                 S_ExtraUpdate ();
3434
3435         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3436         {
3437                 R_DrawModelShadows();
3438
3439                 R_ResetViewRendering3D();
3440
3441                 // don't let sound skip if going slow
3442                 if (r_refdef.extraupdate)
3443                         S_ExtraUpdate ();
3444         }
3445
3446         R_ShadowVolumeLighting(false);
3447         if (r_timereport_active)
3448                 R_TimeReport("rtlights");
3449
3450         // don't let sound skip if going slow
3451         if (r_refdef.extraupdate)
3452                 S_ExtraUpdate ();
3453
3454         if (cl.csqc_vidvars.drawworld)
3455         {
3456                 R_DrawLightningBeams();
3457                 if (r_timereport_active)
3458                         R_TimeReport("lightning");
3459
3460                 R_DrawDecals();
3461                 if (r_timereport_active)
3462                         R_TimeReport("decals");
3463
3464                 R_DrawParticles();
3465                 if (r_timereport_active)
3466                         R_TimeReport("particles");
3467
3468                 R_DrawExplosions();
3469                 if (r_timereport_active)
3470                         R_TimeReport("explosions");
3471         }
3472
3473         if (gl_support_fragment_shader)
3474         {
3475                 qglUseProgramObjectARB(0);CHECKGLERROR
3476         }
3477         VM_CL_AddPolygonsToMeshQueue();
3478
3479         if (r_view.showdebug)
3480         {
3481                 if (cl_locs_show.integer)
3482                 {
3483                         R_DrawLocs();
3484                         if (r_timereport_active)
3485                                 R_TimeReport("showlocs");
3486                 }
3487
3488                 if (r_drawportals.integer)
3489                 {
3490                         R_DrawPortals();
3491                         if (r_timereport_active)
3492                                 R_TimeReport("portals");
3493                 }
3494
3495                 if (r_showbboxes.value > 0)
3496                 {
3497                         R_DrawEntityBBoxes();
3498                         if (r_timereport_active)
3499                                 R_TimeReport("bboxes");
3500                 }
3501         }
3502
3503         if (gl_support_fragment_shader)
3504         {
3505                 qglUseProgramObjectARB(0);CHECKGLERROR
3506         }
3507         R_MeshQueue_RenderTransparent();
3508         if (r_timereport_active)
3509                 R_TimeReport("drawtrans");
3510
3511         if (gl_support_fragment_shader)
3512         {
3513                 qglUseProgramObjectARB(0);CHECKGLERROR
3514         }
3515
3516         if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3517         {
3518                 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3519                 if (r_timereport_active)
3520                         R_TimeReport("worlddebug");
3521                 R_DrawModelsDebug();
3522                 if (r_timereport_active)
3523                         R_TimeReport("modeldebug");
3524         }
3525
3526         if (gl_support_fragment_shader)
3527         {
3528                 qglUseProgramObjectARB(0);CHECKGLERROR
3529         }
3530
3531         if (cl.csqc_vidvars.drawworld)
3532         {
3533                 R_DrawCoronas();
3534                 if (r_timereport_active)
3535                         R_TimeReport("coronas");
3536         }
3537
3538         // don't let sound skip if going slow
3539         if (r_refdef.extraupdate)
3540                 S_ExtraUpdate ();
3541
3542         R_ResetViewRendering2D();
3543 }
3544
3545 static const int bboxelements[36] =
3546 {
3547         5, 1, 3, 5, 3, 7,
3548         6, 2, 0, 6, 0, 4,
3549         7, 3, 2, 7, 2, 6,
3550         4, 0, 1, 4, 1, 5,
3551         4, 5, 7, 4, 7, 6,
3552         1, 0, 2, 1, 2, 3,
3553 };
3554
3555 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3556 {
3557         int i;
3558         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3559         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3560         GL_DepthMask(false);
3561         GL_DepthRange(0, 1);
3562         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3563         R_Mesh_Matrix(&identitymatrix);
3564         R_Mesh_ResetTextureState();
3565
3566         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3567         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3568         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3569         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3570         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3571         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3572         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3573         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3574         R_FillColors(color4f, 8, cr, cg, cb, ca);
3575         if (r_refdef.fogenabled)
3576         {
3577                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3578                 {
3579                         f1 = FogPoint_World(v);
3580                         f2 = 1 - f1;
3581                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3582                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3583                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3584                 }
3585         }
3586         R_Mesh_VertexPointer(vertex3f, 0, 0);
3587         R_Mesh_ColorPointer(color4f, 0, 0);
3588         R_Mesh_ResetTextureState();
3589         R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3590 }
3591
3592 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3593 {
3594         int i;
3595         float color[4];
3596         prvm_edict_t *edict;
3597         // this function draws bounding boxes of server entities
3598         if (!sv.active)
3599                 return;
3600         SV_VM_Begin();
3601         for (i = 0;i < numsurfaces;i++)
3602         {
3603                 edict = PRVM_EDICT_NUM(surfacelist[i]);
3604                 switch ((int)edict->fields.server->solid)
3605                 {
3606                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
3607                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
3608                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
3609                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3610                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
3611                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
3612                 }
3613                 color[3] *= r_showbboxes.value;
3614                 color[3] = bound(0, color[3], 1);
3615                 GL_DepthTest(!r_showdisabledepthtest.integer);
3616                 GL_CullFace(r_view.cullface_front);
3617                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3618         }
3619         SV_VM_End();
3620 }
3621
3622 static void R_DrawEntityBBoxes(void)
3623 {
3624         int i;
3625         prvm_edict_t *edict;
3626         vec3_t center;
3627         // this function draws bounding boxes of server entities
3628         if (!sv.active)
3629                 return;
3630         SV_VM_Begin();
3631         for (i = 0;i < prog->num_edicts;i++)
3632         {
3633                 edict = PRVM_EDICT_NUM(i);
3634                 if (edict->priv.server->free)
3635                         continue;
3636                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3637                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3638         }
3639         SV_VM_End();
3640 }
3641
3642 int nomodelelements[24] =
3643 {
3644         5, 2, 0,
3645         5, 1, 2,
3646         5, 0, 3,
3647         5, 3, 1,
3648         0, 2, 4,
3649         2, 1, 4,
3650         3, 0, 4,
3651         1, 3, 4
3652 };
3653
3654 float nomodelvertex3f[6*3] =
3655 {
3656         -16,   0,   0,
3657          16,   0,   0,
3658           0, -16,   0,
3659           0,  16,   0,
3660           0,   0, -16,
3661           0,   0,  16
3662 };
3663
3664 float nomodelcolor4f[6*4] =
3665 {
3666         0.0f, 0.0f, 0.5f, 1.0f,
3667         0.0f, 0.0f, 0.5f, 1.0f,
3668         0.0f, 0.5f, 0.0f, 1.0f,
3669         0.0f, 0.5f, 0.0f, 1.0f,
3670         0.5f, 0.0f, 0.0f, 1.0f,
3671         0.5f, 0.0f, 0.0f, 1.0f
3672 };
3673
3674 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3675 {
3676         int i;
3677         float f1, f2, *c;
3678         float color4f[6*4];
3679         // this is only called once per entity so numsurfaces is always 1, and
3680         // surfacelist is always {0}, so this code does not handle batches
3681         R_Mesh_Matrix(&ent->matrix);
3682
3683         if (ent->flags & EF_ADDITIVE)
3684         {
3685                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3686                 GL_DepthMask(false);
3687         }
3688         else if (ent->alpha < 1)
3689         {
3690                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3691                 GL_DepthMask(false);
3692         }
3693         else
3694         {
3695                 GL_BlendFunc(GL_ONE, GL_ZERO);
3696                 GL_DepthMask(true);
3697         }
3698         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3699         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3700         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3701         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3702         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3703         if (r_refdef.fogenabled)
3704         {
3705                 vec3_t org;
3706                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3707                 R_Mesh_ColorPointer(color4f, 0, 0);
3708                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3709                 f1 = FogPoint_World(org);
3710                 f2 = 1 - f1;
3711                 for (i = 0, c = color4f;i < 6;i++, c += 4)
3712                 {
3713                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3714                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3715                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3716                         c[3] *= ent->alpha;
3717                 }
3718         }
3719         else if (ent->alpha != 1)
3720         {
3721                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3722                 R_Mesh_ColorPointer(color4f, 0, 0);
3723                 for (i = 0, c = color4f;i < 6;i++, c += 4)
3724                         c[3] *= ent->alpha;
3725         }
3726         else
3727                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3728         R_Mesh_ResetTextureState();
3729         R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3730 }
3731
3732 void R_Draw