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