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