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